on master help sign in
Merge remote-tracking branch 'origin/cleanorg' into cleanorg
commit958b6fb8e662e23c1029248dbfea4318685b9fc2 authorC. Guy Yarvin <cgyarvin@gmail.com> dateThu 21 Apr 2016, 11:12 (11 years ago) parent35eeb230283299
2 files changed+90−38
docs/programming/arvo/system/api.md+33−15 docs/programming/arvo/system/security-driver.md+57−23
docs/programming/arvo/system/api.md+33−15
@@ -87,6 +87,13 @@ The usual flow for implementing this tree of data makes heavy use
8787of the `connector` library. This library is well documented in
8888the source, so check out `/=home=/lib/connector/hoon`.
8989
90+The `connector` library needs to be initialized with definitions
91+of `move` and `sub-result` (all the types of data that can be
92+returned by a place). This can just be a line at the top of the
93+main core:
94+
95+ =+ connector=(connector move sub-result) :: Set up connector library
96+
9097Most of the Github-specific logic is in `++places`, which is a
9198list of all the places we can request. A place consists of:
9299
@@ -120,23 +127,21 @@ list of all the places we can request. A place consists of:
120127 `%y` request must produce an arch, unlike a `%x` request,
121128 which may produce data of any mark.
122129
123−The `connector` library needs to be initialized with definitions
124−of `move` and `sub-result` (all the types of data that can be
125−returned by a place). `read-x` and `read-y` produce moves and
126−`sigh-x` produces a sub-result.
127−
128130Filling out the list of places is a lot of grunt work, but most
129131places are fairly straightforward, and the `++read-*` helper
130132functions are useful. Check out the library source for more
131133information on those.
132134
133135Besides the list of places, we just need to handle the flow of
134−control. There are four functions we need to define:
136+control. `++peek` and `++peer-scry` are the interface we expose
137+to the rest of the system while `++sigh-httr` and `++sigh-tang`
138+are used to handle responses when we make HTTP requests.
135139
136140- `++peek` should usually just produce `~`. If there are cases
137141 where we can respond directly to a `.^` request without
138142 blocking on anything, we could do it here, but it's generally
139− not worth the hassle.
143+ not worth the hassle since the same logic should be duplicated
144+ in `++peer-scry`.
140145
141146- `++peer-scry` is where the actual handling for a read request
142147 goes. In general, we just need to call `++read` from the
@@ -145,11 +150,11 @@ control. There are four functions we need to define:
145150 run either `++read-x` or `++read-y`, depending on the care.
146151
147152- If `++read-x` or `++read-y` made a successful API request, then
148− it'll come back on `++sigh-httr`. Here, we just need to parse
149− out the wire and call `++sigh` from the `connector` library
150− with the list of places, care, path, and HTTP result. This
151− will match the path to the appropriate place and run either
152− `++sigh-x` or `++sigh-y`, depending on the care.
153+ the response will come back on `++sigh-httr`. Here, we just
154+ need to parse out the wire and call `++sigh` from the
155+ `connector` library with the list of places, care, path, and
156+ HTTP result. This will match the path to the appropriate place
157+ and run either `++sigh-x` or `++sigh-y`, depending on the care.
153158
154159- If `++read-x` or `++read-y` made an API request that failed,
155160 then we'll get a stack trace in `++sigh-tang`. Here, we just
@@ -158,12 +163,19 @@ control. There are four functions we need to define:
158163That's really all there is to the reading portion of API
159164connectors.
160165
166+One of the most accessbile ways to jump into Arvo programming is
167+to just add more places to an existing API connector. It's
168+useful, small in scope, and comes in bite-sized chunks since most
169+places are less than ten lines of code.
170+
161171## Listening
162172
163173Listening for events is fairly service-specific. In some
164−services, we poll for changes. For an example of that, check out
165−the Twitter connector. In Github, we power our event streams
166−with webhooks.
174+services, we poll for changes. The Twitter connector has an
175+example of this, but note that it predates the `connector`
176+library and is thus more complicated than it needs to be, and the
177+interface it exposes isn't standard. In Github, we power our
178+event streams with webhooks.
167179
168180For Github, when someone subscribes to
169181`/listen/<user>/<repo>/<events...>`, we want to produce
@@ -202,6 +214,12 @@ standardized, so even if your chosen service is powered by
202214webhooks, your listening code might look rather different. The
203215point is to expose the correct interface.
204216
217+
218+## Github API Connector Code
219+
220+In case the code in `/=home=/app/gh/hoon` drifts out of sync with
221+this doc:
222+
205223```
206224:: This is a connector for the Github API v3.
207225::
docs/programming/arvo/system/security-driver.md+57−23
@@ -8,11 +8,13 @@ title: Security Drivers
88
99A security driver is a file in `/=home=/sec/<tld>/<domain>/hoon`
1010that handles the authentication for all HTTP requests to
11−`https://<domain>.<tld>`. All requests to the domain are
12−filtered through the security driver, which will either decorate
13−the request with the needed credentials if it has them, or else
14−it will guide the user through the process of authenticating
15−Urbit with the service.
11+`https://<domain>.<tld>`. When anything in Urbit makes an HTTP
12+request through `%eyre` (our web server), it checks to see if we
13+have a security driver for the requested domain, and if so
14+filters the request through the driver. The security driver will
15+usually either decorate the request with the needed credentials
16+if it has them, or else it will guide the user through the
17+process of authenticating Urbit with the service.
1618
1719Each web service needs its own security driver, but most of them
1820are pretty standard. We recommend starting with an existing
@@ -121,23 +123,53 @@ in `bale`. `bale` contains:
121123 `++bale`. Thus, in our case, `key` in our bale is of type
122124 `keys:basic-auth`.
123125
124−Additionally, a security driver contains at least one "special"
125−arm. Here, we use `++filter-request`, which is a function which
126−takes a hiss (http request) and produces a `sec-move`, which is
127−one of:
128−
129−- `%send` plus a hiss, which sends the new hiss. This is the
130− case in, for example, basic auth, where all we need to do is
131− add an extra header to the request.
132−- `%give` plus an httr (http response), which immediately returns
133− an http response to the sender.
134−- `%show` plus a purl (parsed url), which displays a message
135− asking the user to visit the given url to continue the
136− authentication process.
137−
138−Every request to a GitHub url will be filtered through
139−`++filter-request`, and we want to add the authentication header
140−to it. Our `++aut` core contains a function
126+Additionally, a security driver contains at least one out of the
127+five "special" arms:
128+
129+- `++filter-request` is a function which takes a hiss (http
130+ request) and produces a `sec-move` (defined in zuse), which is
131+ one of:
132+
133+ * `[%send hiss]`, which sends the new hiss. This is the
134+ case in, for example, basic auth, where all we need to do is
135+ add an extra header to the request.
136+ * `[%give httr]`, where httr is an http response. This
137+ immediately returns an http response to the sender.
138+ * `[%show purl]`, where a purl is a parsed url. This displays
139+ a message asking the user to visit the given url to continue
140+ the authentication process.
141+ * `[%redo ~]`, which redoes the request.
142+
143+ `%eyre` calls `++filter-request` just before sending an HTTP
144+ request to the specified domain. This allows the security
145+ driver to filter the requests, decorating them with
146+ authentication data.
147+
148+- `++filter-response` is a function which takes an httr and
149+ produces a `sec-move`. `%eyre` calls it after receiving an
150+ HTTP response from the specified domain. This allows the
151+ security driver to handle authentication errors, commonly
152+ caused by expired tokens, and retry the request.
153+
154+- `++receive-auth-query-string` is a function that takes a `quay`
155+ (list of query parameters) and produces a `sec-move`. `%eyre`
156+ calls it when it receives a request on the callback url.
157+ Generally, this happens in OAuth after the user has granted
158+ access to the urbit app, and the service makes a request to the
159+ callback url with the code. The security driver should then
160+ make a request to convert the code into an access token.
161+
162+- `++receive-auth-response` is a function that takes an httr and
163+ produces a `sec-move`. `%eyre` calls it when it gets a
164+ response to the request made in `++receive-auth-query-string`.
165+
166+- `++update` is a function which converts old state to a new
167+ format when the security driver gets updated. If you want to
168+ just get rid of the old state, define `++discard-state` as `~`.
169+
170+For basic auth, we only have to worry about `++filter-request`,
171+since all we need to do is add the correct header to each
172+request. Our `++aut` core contains a function
141173`++out-addding-header`, which does exactly what we want.
142174
143175Where do the keys come from, though? Remember we ran
@@ -215,7 +247,9 @@ Now we need a security driver. Use this:
215247
216248The oauth2 library provides the main "engine" in `standard`, just
217249like in basic auth, except that we also have to specify a
218−function to save the access token when we get it.
250+function to save the access token when we get it. It's worth
251+noting that this library is well documented in the source,
252+including examples: `/=home=/lib/oauth2/hoon`.
219253
220254Running `+http://api.github.com/user` tries to make a request to
221255Github with authentication. This loads into the bale the keys,