UNPKG

16 kBMarkdownView Raw
1# atlassian-connect-express-hipchat: Node.js module for Express based HipChat Connect Add-ons
2
3[![Build Status](https://drone.io/bitbucket.org/hipchat/atlassian-connect-express-hipchat/status.png)](https://drone.io/bitbucket.org/hipchat/atlassian-connect-express-hipchat/latest)
4
5`atlassian-connect-express-hipchat` is an NPM module for creating [HipChat Connect](https://www.hipchat.com/docs/apiv2/addons) Add-ons with [Node.js](http://nodejs.org/). HipChat Connect is a variant of [Atlassian Connect](https://developer.atlassian.com/static/connect/docs/) and `atlassian-connect-express-hipchat` is a HipChat compatibility layer on top of [atlassian-connect-express](https://bitbucket.org/atlassian/atlassian-connect-express) (aka, ACE).
6
7## More about `atlassian-connect-express-hipchat`
8
9The `atlassian-connect-express-hipchat` package helps you get started developing add-ons quickly, using Node.js and Express as the add-on server.
10
11It's important to understand that [Express](http://expressjs.com/) by itself is a web app framework for Node. `atlassian-connect-express-hipchat` just provides a library of middleware and convenience helpers that make it easier to build HipChat add-ons. Specifically, `atlassian-connect-express-hipchat` adds:
12
13* Automatic JWT authentication of inbound requests
14* Automatic persistence of host details (i.e., client information)
15* HipChat client for communicating with the HipChat REST API
16
17## Getting Started
18
19The fastest way to get started is to install the `atlas-connect` CLI tool. The CLI makes it possible to generate a `atlassian-connect-express-hipchat` enabled add-on scaffold very quickly. To install:
20
21 npm i -g atlas-connect
22
23### Create a project
24
25Let's start by creating an add-on project:
26
27 atlas-connect new -t hipchat <project_name>
28
29This creates a new project home directory with the following contents:
30
31 .
32 ├── Procfile
33 ├── README.md
34 ├── app.js
35 ├── atlassian-connect.json
36 ├── config.json
37 ├── lib
38 │   └── hipchat.js
39 ├── package.json
40 ├── public
41 │   ├── css
42 │   │   └── addon.css
43 │   └── js
44 │   └── addon.js
45 ├── routes
46 │   └── index.js
47 └── views
48 ├── config.hbs
49 └── layout.hbs
50
51### Install dependencies
52
53Change to the new project directory and install dependencies:
54
55 npm install
56
57### Setting up a development environment
58
59The development workflow for building HipChat add-ons is rad. You can build your add-on locally while running it inside of <https://hipchat.com>. To do this, you'll need to expose your local webserver to the internet. An easy way to do this is to use a [local tunnel](http://en.wikipedia.org/wiki/Tunneling_protocol). We highly recommend using [ngrok](https://ngrok.com/). `ngrok` is a simple client tool that allows you to forward internet requests on an ngrok subdomain to your local server:
60
61 ngrok -subdomain <subdomain-name> <port>
62
63### Running your Add-on Server
64
65Once you've started your tunnel, you can run your add-on server:
66
67 AC_LOCAL_BASE_URL=https://<subdomain>.ngrok.com node app.js
68
69This will boot up your add-on server on the default port of 3000. The `AC_LOCAL_BASE_URL` environment variable tells your add-on to use the specified base URL instead of <http://localhost:3000>.
70
71### The Dev Loop
72
73At this point, you can start building your add-on. Changes to views load automatically, however, if you make changes to any JavaScript, you need to restart your add-on server. If you want your server to automatically restart when your JavaScript changes, consider using [nodemon](https://npmjs.org/package/nodemon).
74
75 AC_LOCAL_BASE_URL=https://<subdomain>.ngrok.com nodemon app.js
76
77### Registering your Add-on with HipChat
78
79To get your add-on into HipChat, you have to register your addon's `atlassian-connect.json` descriptor. This descriptor will be accessible through:
80
81 https://<subdomain>.ngrok.com/atlassian-connect.json
82
83HipChat add-ons can operate inside a room or within the entire account. When developing, you should probably register your add-on inside a room you've created just for testing. Also, you can only register add-ons inside a room where you are an administrator.
84
85To register your add-on descriptor, navigate to the rooms administration page:
86
87 https://<your-account>.hipchat.com/rooms
88
89Then select one of your rooms in the list. In the following page, select `Add-ons` in the sidebar:
90
91![Add-on administration](http://f.cl.ly/items/1w2S2z2c3g0k031x3S1d/HipChat%20-%20HipChat%20Add-ons%202014-02-11%2010-32-48.png)
92
93Below the page, you'll find the **Create new private add-ons** form. Paste your descriptor URL in the **Capabilities URL** field then save. This will initiate the installation of your add-on inside the room.
94
95### Configuration
96
97The configuration for your add-on is done in two files:
98
99* `./config.json` -- This file contains the configuration for each runtime environment your add-on runs in. The file has comments to help you understand available settings.
100* `./atlassian-connect.json` -- This file is a manifest of all the extension points your add-on uses. To see all of the available extension point options, take a look at the [HipChat Add-on Capabilities page](https://www.hipchat.com/docs/apiv2/method/get_capabilities).
101
102#### config.json
103
104The `./config.json` file contains all of the settings for the add-on server. This file is divided into runtime environments. The default template includes `development` and `production`, but you're free to add any other environments you'd like to use.
105
106To run your add-on in a specific environment, use the `NODE_ENV` environment variable:
107
108 NODE_ENV=<environment> AC_LOCAL_BASE_URL=https://<subdomain>.ngrok.com nodemon app.js
109
110
111### atlassian-connect.json
112
113The `atlassian-connect.json` describes what your add-on will do. There are two main parts to the descriptor: meta information that describes your add-on (i.e., name, description, key, etc.) and a list of the modules your add-on will provide. This descriptor is registered with HipChat when your add-on is installed.
114
115To see all of the available settings in the `atlassian-connect.json`, take a look at the [HipChat Add-on Capabilities page](https://www.hipchat.com/docs/apiv2/method/get_capabilities).
116
117## Sample Add-ons using `atlassian-connect-express-hipchat`
118
119* [GitHub](https://bitbucket.org/hipchat/hipchat-github-addon) -- get notified of events that happen on GitHub inside your HipChat rooms
120* [Instagram](https://bitbucket.org/hipchat/hipchat-instagram-addon) -- get room notifications when someone posts a photo matching a tag you're watching
121
122## The `atlassian-connect-express-hipchat` scaffold
123
124When you generate a new `atlassian-connect-express-hipchat` add-on, you're actually just downloading a copy of the [Atlassian Connect Expressjs template](https://bitbucket.org/atlassian/atlassian-connect-express-template/src/hipchat/).
125
126### Handlebars layouts and templates
127
128The base scaffold uses the [Handlebars](http://handlebarsjs.com) template library via the [express-hbs](https://github.com/barc/express-hbs) package.
129
130Handlebars views are stored in the `./views` directory. The base template contains a `layout.hbs` and a configuration page (`config.hbs`). Handlebars alone doesn't provide layouts, but the `express-hbs` package does. To apply the `layout.hbs` layout to your template page, just add the following to the top of your template:
131
132 {{!< layout}}
133
134To learn more about how Handlebars works in Expressjs, take a look at the [express-hbs documentation](https://github.com/barc/express-hbs#readme).
135
136### Special context variables
137
138`atlassian-connect-express-hipchat` injects a handful of useful context variables into your render context. You can access any of these within your templates:
139
140* `title`: the add-on's name (derived from `atlassian-connect.json`)
141* `appKey`: the application key defined in `atlassian-connect.json`
142* `localBaseUrl`: the base URI of the add-on
143* `hostStylesheetUrl`: the URL to the base CSS file for Connect add-ons. This stylesheet is a bare minimum set of styles to help you get started. It's not a full AUI stylesheet.
144* `hostScriptUrl`: the URL to the Connect JS client. This JS file contains the code that will establish the seamless iframe bridge between the add-on and its parent. It also contains a handful of methods and objects for accessing data through the parent (look for the `AP` JS object).
145* `signed_request`: a JWT token that can be used to authenticate calls from the iframe back to the add-on service.
146
147You can access any of the variables above as normal Handlebars variables. For example, to generate a link in your page that links elsewhere in the host:
148
149 <a href="{{hostBaseUrl}}/config">Configuration</a>
150
151## Recipes
152
153### How to secure a route with JWT
154
155Add-ons are authenticated through [JWT](http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-15). To simplify JWT verification on your routes, you can simply add a `atlassian-connect-express-hipchat` middleware to your route:
156
157 module.exports = function (app, addon) {
158 app.get('/protected-resource',
159
160 // Protect this resource with JWT
161 addon.authenticate(),
162
163 function(req, res) {
164 res.render('protected');
165 }
166 );
167 };
168
169Simply adding the `addon.authenticate()` middleware will protect your resource. It will also make available some useful `request` properties that will be useful in your app:
170
171* `req.clientInfo`: useful information about the add-on client such as the clientKey, oauth info, and HipChat account info
172* `req.context`: contains the context data accompanying the request like the roomId
173
174It also populates the `res.signed_request` property that can be used to expose the JWT token to your pages for subsequent requests back to your add-on server.
175
176### How to send a signed HTTP request from the iframe back to the add-on service
177
178The initial call to load the iframe content is secured by JWT, as described above. However, the loaded content cannot sign subsequent requests. A typical example is content that makes AJAX calls back to the add-on. Cookie sessions cannot be used, as many browsers block third-party cookies by default. `atlassian-connect-express-hipchat` provides middleware that works without cookies and helps making secure requests from the iframe.
179
180A route can be secured by adding the `addon.authenticate()` middleware:
181
182 module.exports = function (app, addon) {
183 app.get('/protected-resource',
184
185 // Require a valid token to access this resource
186 addon.authenticate(),
187
188 function(req, res) {
189 res.render('protected');
190 }
191 );
192 };
193
194In order to secure your route, the token must be part of the HTTP request back to the add-on service. This can be done by using a query parameter:
195
196 <a href="/protected-resource?signed_request={{signed_request}}">See more</a>
197
198The second option is to use an HTTP header, e.g. for AJAX requests:
199
200 beforeSend: function (request) {
201 request.setRequestHeader("X-acpt", {{token}});
202 }
203
204You can embed the token anywhere in your iframe content using the `token` content variable. For example, you can embed it in a meta tag, from where it can later be read by a script:
205
206 <meta name="acpt" content="{{signed_request}}">
207
208Both the query parameter `acpt` and the HTTP request header `X-acpt` are automatically recognized and handled by `atlassian-connect-express-hipchat` when a route is secured with the `addon.authenticate()` middleware. The token remains valid for 15 minutes by default, and is automatically refreshed on each call. The expiration of the token can be configured using `maxTokenAge` (in seconds) inside `config.json`.
209
210### How to send a signed outbound HTTP request back to the host
211
212`atlassian-connect-express-hipchat` bundles and extends the [request](https://github.com/mikeal/request) HTTP client. To make a request back to the HipChat, all you have to do is use `request` the way it was designed. REST calls back to HipChat require that you use the `access_token` provided to you at installation.
213
214To make things easier, we've provided a simple HipChat client for sending messages found inside `./lib/hipchat.js`. To use this, all you have to do is:
215
216 var hipchat = require('../lib/hipchat')(addon);
217
218 // This is an example route to handle an incoming webhook
219 app.post('/webhook',
220 addon.authenticate(),
221 function(req, res) {
222 hipchat.sendMessage(req.clientInfo, req.context.item.room.id, 'pong')
223 .then(function(data){
224 res.send(200);
225 });
226 }
227 );
228
229### How to persist data for your add-on
230
231`atlassian-connect-express-hipchat` bundles a [Redis](http://redis.io/) [adapter](https://bitbucket.org/atlassianlabs/atlassian-connect-express-redis). *To use Redis with your add-on, you should install Redis locally.*
232
233You don't have to use Redis, but the default template makes use of Redis. Redis is awesome for building add-ons, but you're free to use whatever you'd like. We also bundle [JugglingDB](http://jugglingdb.co/) (a cross-database ORM for nodejs) which works with a variety of databases.
234
235If you choose to use Redis, congratulations on *doing the right thing*. But more importantly, you might also want to use [redis-commander](https://github.com/joeferner/redis-commander) to manage your Redis data. It's extremely helpful to see what's getting stored in your DB.
236
237### How to deploy to Heroku
238Before you start, install Git and the [Heroku Toolbelt](https://toolbelt.heroku.com/).
239
240If you aren't using git to track your add-on, now is a good time to do so as it is required for Heroku. Ensure you are in your project home directory and run the following commands:
241
242 git config --global user.name "John Doe"
243 git config --global user.email johndoe@example.com
244 ssh-keygen -t rsa
245 git init
246 git add .
247 git commit . -m "some message"
248 heroku keys:add
249
250Next, create the app on Heroku:
251
252 heroku apps:create <add-on-name>
253
254Then set the public and private key as environment variables in Heroku (you don't ever want to commit these `*.pem` files into your scm). The two `.*pem` files were created in your project home directory when you ran the `atlas-connect new` command.
255
256 heroku config:set AC_LOCAL_BASE_URL=https://<subdomain> herokuapp.com --app <add-on-name>
257 heroku config:set DATABASE_URL=<DB URL> --app <add-on-name>
258
259Lastly, let's add the project files to Heroku and deploy!
260
261If you aren't already there, switch to your project home directory. From there, run these commands:
262
263 git remote add heroku git@heroku.com:<add-on-name>.git
264 git push heroku master
265
266It will take a minute or two for Heroku to spin up your add-on. When it's done, you'll be given the URL where your add-on is deployed, however, you'll still need to register the `atlassian-connect.json` descriptor on HipChat.
267
268For further detail, we recommend reading [Getting Started with Node.js on Heroku](https://devcenter.heroku.com/articles/getting-started-with-nodejs).
269
270## Troubleshooting
271
272### Debugging HTTP Traffic
273
274If you're using `ngrok`, you can point your browser to <http://localhost:4040> to access `ngrok`'s built-in traffic analyzer.
275
276## Getting Help or Support
277
278You can get help by emailing <atlassian-connect-dev@googlegroups.com> or [report bugs](https://bitbucket.org/hipchat/atlassian-connect-express-hipchat/issues?status=new&status=open). If you want to learn more about HipChat Connect, you can visit <https://www.hipchat.com/docs/apiv2/addons>.
279
280## Contributing
281
282Even though this is just an exploratory project at this point, it's also open source [Apache 2.0](https://bitbucket.org/atlassian/atlassian-connect-express-hipchat/src/master/LICENSE.txt). So, please feel free to fork and send us pull requests.