Tutorial: extending the zend server ui and web api
1. Extending the Zend Server
UI and WebAPI
Adding your own functionality to Zend Server
Presented by Yonni Mendes with cats, spartans, pirates and Obama!
Presented by Yonni Mendes, ZS6 UI Tech Leader
Before we start, kindly visit avast.yonman.net
and install the listed applications & stuff!
2. Setup: what you should have
● Zend Studio, or other IDE of choice
● Zend Server
● AhoyWorld zpk deployable
● Tutorial package
○ Skeletons
○ Exercise snippets
○ Complete code
● Recommended
○ Chrome: Dev HTTP Client or similar
○ Firefox: Firebug, live HTTP Headers or similar
3. Who and What is a Yonni
● A restaurant in Los Angeles, California.
Sadly, closed.
● A semi-famous male model
● The UI Technological Leader for Zend Server
Also
● A father
● A gamer
● A technologist
Ask me about the extra thing
Stuff you need:
IDE
Zend Server
Ahoy World
Chrome: Dev HTTP
Firefox: Firebug, live
HTTP Headers
Sqlite database manager
of choice
4. But first…
Some exercises to
get the blood
flowing
Stand up please!
Stuff you need:
IDE
Zend Server
Ahoy World
Chrome: Dev HTTP
Firefox: Firebug, live
HTTP Headers
Sqlite database manager
of choice
5. Topics
• Create a basic 3rd party module
• Understanding ZS6
o Under the Zend Server 6 hood
o Beasts and common practices of ZS6
o Lets make our module do something
• Some more modules that
are out there
Stuff you need:
IDE
Zend Server
Ahoy World
Chrome: Dev HTTP
Firefox: Firebug, live
HTTP Headers
Sqlite database manager
of choice
6. Why extend ZS6?
● Zend Server’s unique position
● Zend Server’s existing platform & services
Stuff you need:
IDE
Zend Server
Ahoy World
Chrome: Dev HTTP
Firefox: Firebug, live
HTTP Headers
Sqlite database manager
of choice
And, for us, most
importantly:
B.W.C
8. A few ZF2 buzzwords
These are a few devices we will need
● ServiceManager, Factories
● Merged config arrays
● Modules, Module manager
9. Our scenario
● We have an application, “Ahoy World!”
○ Deploy it
(https://github.com/YonmaN/AhoyWorld)
● This application can be turned on and off
● We want to allow a user logged into Zend
Server to control this toggle directly from the
UI
● We also want to control this toggle from other remote
sources via WebAPI
10. Andy the admin’s req’s
• Show some general app information
• Access to toggle the application state
o Anywhere, Anytime, but not direct access
o No access to those Creative Type People over at
marketing
• Human UI and API access
• Must be secure
o But: Do not create a new user authentication system,
nor modify the existing one at Ahoy
• In fact, do not modify AhoyWorld at all
11. Our Module: Avast
● WebAPI will allow a client to:
○ Retrieve the current status of the site (on or off)
○ Toggle the current status of the site
○ Rely on external code that’s included into the
module
● UI will display the deployment information
about our application
● UI will only show a status indicator to the
developer, nothing else
● UI will show a toggle button that allows the
admin to turn the site on or off
12. Functional requirements
● ZF2 module, use ZF2 features, be ZF2
compliant
● WebAPI will return both json and xml
output
● UI page will be integrated in the ZS6 ACL
● UI page will show up in the navigation page
● UI will be accessible only to a logged in user
13. Preparing to develop for ZS6
• Switch off opcode cache in Zend Server
o Linux/mac:
/usr/local/zend/gui/lighttpd/etc/conf.d/optimizerplus.ini
o Windows: Through the UI (Configuration|Components)
• Restart Zend Server
o Throught the UI (localhost:10081)
o Command line (<install_dir>/bin/zendctl.sh
restart)
• Recommended:
open <install_dir>/gui as a php project in the
IDE
14. Warning! Confusion ahead!
● Zend Studio copies files
● Changes may not apply
● You may have to make some changes
manually
● Particularly, the vendor library changes
15. Creating a new module, the
hard way
● Create a new php project
● zendframework/ZendSkeletonModule
● Unzip into your workspace folder
● Rename everything that needs renaming
16. Rename gotta rename
● Folder names
○ in src
● File names
○ Controller filename
○ view scripts
● Controller class name
17. Create a new module, the
easy way
● Create a new php project
● Unzip avast.yonman.net/Avast-00-Initial.zip
Important: can you create a symbolic link?
Recommended: add the Zend GUI project as a
library to the new module project, in ‘include
path’
18. Make a connection
● In the Zend Server UI directory
o link to ./vendor
o Add ‘Avast’ to application.config.php
• Open localhost:10081/ZendServer/Avast
Note case sensitive URL
Result: error :(
20. ACL entries and overrides
• Pitfall: GUI will now return 404!
o Bug in the ACL system
o Missing resource called "skeleton"...
o Therefore no controller is found ... ergo 404
• Fix: ACL requires SQL entries
o sqlite: var/db/gui.db or data/db/gui.db
INSERT OR IGNORE INTO GUI_ACL_RESOURCES VALUES(NULL,'route:Avast');
INSERT OR IGNORE INTO GUI_ACL_PRIVILEGES VALUES(3, last_insert_rowid(), '');
(Place in sqls in a dedicated sql file - acl.sqlite.entries.sql)
Result: localhost:10081/ZendServer/Avast
should respond correctly
Exercise Avast-01-acl
21. Installation process
summary
• Unpack / link module into ./vendor
• Add module name to application.config.php
• Run SQLs
• Copy any config.php files into
./config/autoload
• Copy any public directory assets to the
public direcotry (js, images, css)
22. Bask in the glory of your
Module!
Our module can now:
● Display an empty page
● Override navigation bar
● Display app info & status indicator
● Provide WebAPI control of Ahoy
● Provide a UI button to control Ahoy
24. Lets grease those elbows!
From here on:
1. Describe a tool or ZS6 subsystem and its use
2. Show its usage in the ZS6 codebase
3. Integrate it to some extent into your module
Our goal:
1. Create a functioning, usable module for ZS6
2. Module will provide functionality in webapi
3. Module will also provide a UI interface to use the above functionality
4. Have fun!
25. Files you might want to
watch
Linux
● gui/lighttpd/logs/zend_server_ui.log
● gui/lighttpd/logs/php.log
Windows
● logs/zend_server_ui.log
● logs/php.log
You can access both through the Zend Server
UI (Overview|Logs)
26. ZF2: Navigation override
• navigation.global.config.php
• We wish to add a new Avast tab
• Tab should use Avast controller
Exercise: Override the navigation
array in
Avast/module.config.php
Ask me about ZS6.2!
Result: Navigation bar should Exercise Avast-02-navigation
27. Calling the ZS databases
• You’ll want to do this through our mappers
• If you want to build a new mapper ...
o ServiceManager and delegated Di
DbConnector::factory
Driver
Connection
Adapter
TableGateway
Mapper
o Can also call ServiceManager->get('PDO')
28. Spotlight:
DeploymentFilteredAccessMapper
● Wraps another mapper, which wrapper yet
another, foreign mapper. Good times.
● Things of interest
○ FilteredAccessMapper::getMasterApplicationsByIds
○ DeploymentApplicationContainer
Ask me about the big dirty lie!
29. An aside:
Foreign code, a cruel mistress
● Next we will implement
○ Avast UI has to show deployment information about
“Ahoy World”
○ Use DeploymentFilteredAccessMapper class to
retrieve and display data
● Use foreign code carefully to avoid errors
● Aggregate, don’t inherit (Ask me why )
● Avoid referring to foreign code directly
30. Lets integrate
Recommended approach:
● Create an aggregating class for
FilteredAccessMapper
● Implement findAhoyApplication() code in class
● Integrate your class into the controller
Can go the extra mile - wrap the application
container that is returned
31. Calling the database
● Avast UI has to show deployment information
about “Ahoy World”
● Use DeploymentFilteredAccessMapper class
to retrieve and display data
Exercise: Integrate a call to retrieve all
applications. Find ‘Ahoy World’ application
data.
Show this data in your view script.
Ask me why there’s no native
“getApplicationByName” method!Exercise Avast-03-applications
32. Add a visual status indicator
Requirement:
● UI will show a toggle status indicator for
Ahoy World
Thoughts on how to integrate with the
AhoyWorld Application?
34. Add a visual status
indicator...
Requirement:
● UI will show a toggle status indicator for
Ahoy World
Exercise:
Add a static visual indicator for the current
state.
Retrieve result without duplicating functionality
Result: Visual indicator will display correct info
Exercise Avast-04-StatusIndicator
35. Bask in the glory of your
Module!
Our module can now:
● Display an empty page
● Override navigation bar
● Display app info & status indicator
● Provide WebAPI control of Ahoy
● Provide a UI button to control Ahoy
37. WebAPI: How does one use
it
• Create a request using ZendHttpClient
• Add an Accept header
o application/vnd.zend.serverapi+json
o Can be X-Accept too (Ask me why!)
• Sign the request using
SignatureGenerator
o Date should be a GMT with specific format
o Use key obtained in the WebAPI section of UI
o Machines may have to have their clocks synched
Good news: We don’t need any of the above
38. Tools: Request simulation
How about we see an example?
● URL: localhost:10081/ZendServer/Api/getSystemInfo
● Header: Accept: ….
○ To version or not to version?
■ application/vnd.zend.serverapi+json;version=1.5
○ Output type?
● Get or post?
● Signed request or session hijacking?
● Inspecting the response
39. WebAPI: avastAhoyStatus
● WebAPI action to return the current state of
Ahoy’s master directive
● No parameters
● Output: json and xml
We want to create the avastAhoyStatus route &
ACL
…
but how do we do that?
40. Create a WebAPI route
Create a Literal route in module.config.php
'webapi_routes' => array(
'AvastWebAPI' => array(
'type'=> 'ZendMvcRouterHttpLiteral',
'options' => array(
'route' => '/Api/example',
'defaults' => array(
'controller' => 'AvastWebAPI',
'action' => 'avastAhoyStatus',
'versions' => array('1.5'),
),
))
)
...
Ask me about more route options!
Tell me: what did I forget?
41. More ACL entries and
overrides
• ACL requires SQL entries
o sqlite, db/gui.db
INSERT OR IGNORE INTO GUI_ACL_RESOURCES VALUES(NULL,'route:AvastWebAPI');
INSERT OR IGNORE INTO GUI_ACL_PRIVILEGES VALUES(3, last_insert_rowid(), '');
• These queries have to be reapplied after
upgrades
• Controller names are case sensitive
Ask me about exceptions!
42. avastAhoyStatus, cont’d
Reminder:
● WebAPI action to return the current state of
Ahoy’s master directive
● No parameters
● Output: json and xml
We want to create a controller and view scripts
…
but how do we do that?
43. Lets add a WebAPI
controller
• Class WebAPIController
o Extends WebAPIActionController class
o Add to controllers in module.config
(AvastWebAPI_1-5)
o Controller names are case sensitive
• Action should be named as indicated by the
route’s action parameter
44. Lets add a WebAPI view
script
• Actions need View scripts - one for each
format
o avast/web-api/1x5/<action>.pjson.phtml
o avast/web-api/1x5/<action>.pxml.phtml
o <action> has dashed inflection: avast-
ahoy-status
o Wrapped by layout.p<output>.phtml automatically
o Create a string that “nestles” within the layout
• View script has to include “responseData”
wrapper element in json and xml
45. avastAhoyStatus, cont’d
● WebAPI action to return the current state of
Ahoy’s master directive
● No parameters
● Output: json and xml
Exercise: Create the avastAhoyStatus webapi
controller & action
Exercise: Create json and xml view scripts
Use dummy data for this exercise
Result: avastAhoyStatus responds to requests
46. avastAhoyStatus
functionality
● Add functionality to our webapi action
● Retrieve a boolean status
● Pass it out to the view script
Exercise: Use Integration Stub to retrieve status
Replace the dummy data from the previous
exercise
Result: avastAhoyStatus responds correctly
Exercise Avast-05-avastAhoyStatus
47. WebAPI: avastAhoyToggle
● WebAPI action to return the updated state of
Ahoy’s master directive
● Parameter: state
● Output: json and xml
Exercise: Create the avastAhoyToggle route
Exercise: Create the avastAhoyToggle webapi
Exercise: Create json and xml output, similar or
identical to avastAhoyStatus
Result: avastAhoyToggle responds to requests
48. WebAPI: avastAhoyToggle
● Add functionality to our webapi action
● Collect a parameter and validate it
● Pass the parameter to a toggle method
Exercise: Use <ahoyworld-url>/Status/Toggle to change
AhoyWorld’s status
Result: calls to avastAhoyToggle affect
AhoyWorld
Exercise Avast-06-avastAhoyToggle
49. Bask in the glory of your
Module!
Our module can now:
● Display an empty page
● Override navigation bar
● Display app info & status indicator
● Provide WebAPI control of Ahoy
● Provide a UI button to control Ahoy
51. Javascript!
● WebAPI is everywhere in the UI
● Different usage scenarios
● Some tools we provide
○ zswebapi.js
○ zgridPolling.js
○ FragmentManager.js
Ask me about the exceptions to the rule!
52. Integrate WebAPI into the
UI
● Status indicator
● Button that will call our toggle webapi
● Use toggle response to update indicator
Exercise: use Request.WebAPI to call the toggle
Result: We have a button that lets the user
affect AhoyWorld directly
Exercise Avast-07-webapiButton
54. ACL in Zend Server
• ACL is consulted for every request
• Two ACLs: Role/Identity, Edition/License
o Identity ACL initialized from the database
GUI_ACL_ROLES, GUI_ACL_RESOURCES,
GUI_ACL_PRIVILEGES
Roles: administrator, developer,
developerLimited
o License ACL initialized within the application
55. ACL in Zend Server
• ACL Resources are prefixed:
o route - to indicate this is an MVC controller resource
o data - to indicate this is a logical resource
o service - to indicate this is a system-wide resource
• Privileges may allow particular actions
56. ACL in Zend Server, cont'd
• AclQuery class, registered services
o ZendServerAcl (AclQuery class)
o ZendServerEditionAcl (Acl class)
o ZendServerIdentityAcl (Acl class)
• AclQuery is used many places
• AclQuerierInterface sets ZendServerAcl
o ZendServer..PhpRenderer - for view usage
o ZendServer..ActionController - inherited by every
controller in the ZS6 UI application
o ZendServer..DefaultNavigationFactory for
navigation rendering
o and others...
57. ACL: limit access to WebAPI
● avastAhoyStatus should be accessible to
admin and developer alike
● avastAhoyToggle should be accessible to the
admin only
Exercise: Modify your module’s SQLs to map
these ACL directives. Apply the new
directives immediately to your gui.db and
acl.sqlite...sql
Result: Developer user gets an error for toggleExercise Avast-08-webapiAclLimit
58. ACL: querying in MVC
● Acl Queries can be performed in view script
○ PhpRenderer::isAllowed()
○ PhpRenderer::isAllowedIdentity()
○ PhpRenderer::isAllowedEdition()
● Acl Queries can also be used in controllers
○ ActionController::isAclAllowed()
○ ActionController::isAclAllowedIdentity(
)
○ ActionController::isAclAllowedEdition()
60. ACL: limit access to WebAPI
● avastAhoyStatus should be accessible to
admin and developer alike
● avastAhoyToggle should be accessible to the
admin only
Exercise:
Add an isAclAllowed check in Controller action
If fails, throw a WebAPIException
Exception Code: INSUFFICIENT…
Result: action doesn’t fail… what did we forget?
61. ACL: limit access, cont’d
● avastAhoyStatus ... admin and developer
● avastAhoyToggle should be accessible to the
admin only
Exercise:
Modify SQLs to map ACL directives. Apply the
new directives immediately to your gui.db
Result: Developer user gets an error for toggle
Ask me about the neat trick!
Exercise Avast-08-webapiAclLimit
62. ACL: affecting presentation
● Ahoy status indicator should be visible to
anyone
● Ahoy toggle button should be available only
to an administrator
Exercise: Add ACL queries to the view script
Result: Ahoy toggle button does not get
displayed at all to the developer
Exercise Avast-09-uiAclLimits
63. Bask in the glory of your
Module!
Our module can now:
● Display an empty page
● Override navigation bar
● Display app info & status indicator
● Provide WebAPI control of Ahoy
● Provide a UI button to control Ahoy
65. Add polling to the Avast
page
● zgridPolling, Request.WebAPI
○ Poll avastAhoyStatus
○ Polling populates button label and indicator label
● Polling removes the need to refresh the page
after toggle button is pressed
66. Calling the database:
extended
● Clusters require we show the application
status for every server, not just its aggregate.
● Show each server’s state for AhoyWorld
● ServersDbMapper methods will assist
Exercise: Use the application’s servers list to
cross reference with the available servers list
67. Create an avastAppInfo
WebAPI
● Move the functionality of retrieving
application data form the UI into a webapi
action
● This can be used for page display by polling
avastAppInfo from the page
69. Logging
• Zend Server UI log: zend_server_ui.log
o Linux: <zend-server>/gui/lighttpd/logs
o Windows: <zend-server>logs
o Written to by class ZendServerLogLog
• Verbosity change be changed in the Settings
o Default value is notice and up
• Logs can be viewed in the Logs page
o Relies on GUI_AVAILABLE_LOGS table
o You can add logs, table is cleared during upgrade
70. Debugging the ZS UI
When debugging your module inside ZS6:
● Log verbosity should stay on notice
○ Throw out messages in high levels like “alert”
○ Debug level throws out LOTS of information
● UI is constantly polling, you may face lots of
log entries that are unrelated to your own
code
○ zend_gui.debugModeEnabled = true adds the
request URI to the log entry
○ Allows you to filter the entries
71. ...
IdentityFilter -
Authentication
• Simple Authentication
• Extended Authentication
o Identity Groups
o Groups to Apps mapping
o CustomAuth module
• Login
o Authenticate user credentials
o Create session Identity object
o Determine allowed applications
o End result: Identity has a list of
allowed applications
User
Groups
Listof
Apps
Group1
Group2
Group3
App 1
App 2
Zend Server
LDAP
Session
storage
72. IdentityFilter - Use and
usage
• Classes implement IdentityFilterInterface
interface IdentityFilterInterface {
public function filterAppIds($applicationIds, $emptyIsAll);
public function setAddGlobalAppId($addGlobalAppId);
}
• filterAppIds
o Intersect identity applications with $applicationIds
o If empty applications, check $emptyIsAll
• setAddGlobalAppId
o Global application (Ask me what that is!)
73. UI compounded services
• Compound services
o Controllers call other controllers using forward-
>dispatch plugin
o MVC Failures are handled by dispatch.error event
and event handlers
o Nested WebAPI calls in clusters (An example?)
• View scripts
o Some initial data is rendered by calling a relevant
view script directly
o Using WebAPI from the Zend Server UI client is
easy! (ask me why!)
74. Nested webapi requests
Somewhere
in the
internet...
WebAPI Request
Zend
Server
Webapi
Should I respond
to this request?
Zend
Server
Webapi
ZS6
cluster
dbUsed by:
• Logs display
• Server info
• Codetracing details view
75. WebAPI validation
Set of validation functions that throw
exceptions
• Integrated into all existing webapi actions
• ZendServerMvcControllerWebAPIActionController
• ZendServerMvcControllerActionController
76. Existing ZS6 Modules
● Populated with code written by Zend
developers
● No warranty and no SLA cover
● Highlights
○ ZendServer-TokenAuthentication
○ ZendServer-CustomAuth
○ ZendServerNagiosPlugin
● External and peripheral integration
○ ZendServerWebApiModule
○ ZendServerSDK
○ ZendServerDeploymentHelper