def _auth_creds(creds): def _auth(rej, res): try: if creds == Nothing: # if credentials not in cache, # redirect to the flow authorize URL (step 1 of OAuth dance) # rej( exc.HTTPFound( location=str(flow.step1_get_authorize_url()))) else: # if credentials are in cache, # resolve to (http, authurl, req) where # - http is an httplib2 client authorized with the credentials. # - authurl is the flow authorize URL # # Note that oauth2client.client.AccessTokenRefreshError should be # caught by downstream tasks where the authorized http is used, and # redirect to authurl. This is less than ideal. # res((authorized_http(creds.value), flow.step1_get_authorize_url(), req)) except Exception as e: rej(err.wrap(e)) return Task(_auth)
def _delete(key): def _delete_task(rej, res): try: res(key.delete()) except Exception as e: rej(err.wrap(e)) return Task(_delete_task)
def render(tmpl, data): def _render(rej, res): try: res(tmpl.render(data)) except Exception as e: rej(err.wrap(e)) return Task(_render)
def delete(self, uid): def _delete(rej, res): try: key = ndb.Key(self._model, uid) res(key.delete()) except Exception as e: rej(err.wrap(e)) return Task(_delete)
def put(self, uid, val): def _put(rej, res): try: ent = self._model.get_or_insert(uid) setattr(ent, self._prop, val) res(ent.put()) except Exception as e: rej(err.wrap(e)) return Task(_put)
def get(key): # String -> Task Exception (Maybe a) def _get(rej, res): try: r = memcache.get(key) res(Nothing if r is None else Just(r)) except Exception as e: rej(err.wrap(e)) return Task(_get)
def get_multi(prefix, keys): # String -> List String -> Task Exception (List (Maybe a)) def _get_multi(rej, res): try: r = memcache.get_multi(keys, key_prefix=prefix) res([ Nothing if r.get(k) is None else Just(r.get(k)) for k in keys ]) except Exception as e: rej(err.wrap(e)) return Task(_get_multi)
def get(self, uid): def _get(rej, res): try: ent = self._model.get_by_id(uid) if ent is None: res(Nothing) else: res(Just(ent)) except Exception as e: rej(err.wrap(e)) return Task(_get)
def add_with_time(time, key, value): def _add(rej, res): try: r = None if time is None: r = memcache.add(key, value) else: r = memcache.add(key, value, time=time) if bool(r): res(value) else: raise MemcacheAddFailure(key, value) except Exception as e: rej(err.wrap(e)) return Task(_add)
def callback(params, cache, secret, req, uid): # OAuthParams -> # {put: id -> Credentials -> Task Exception x} -> # String -> # Request -> # id -> # Task HTTPException Dict # Unless error, # do the OAuth exchange to get credentials # store the credentials in cache # redirect to the originally requested URI, # as XSRF-protection-encoded in the 'state' param of credentials # def _exchange(rej, res): if req.params.has_key('error'): # if request has 'error' param, reject with Unauthorized error (401) # note I'm not sure about using this response # comment = req.params.get('error_description', req.params.get('error', '')) rej(exc.HTTPUnauthorized(comment=comment)) else: # otherwise, resolve to credentials of OAuth exchange (step 2 of dance) # try: flow = webserver_flow(params, req, {}) res(flow.step2_exchange(req.params)) except Exception as e: rej(err.wrap(e)) def _cache_and(creds): # Credentials -> Task Exception Credentials # return cache.put(uid, creds).fmap(always(creds)) def _get_redirect(creds): # Credentials -> Task Exception String # uri = xsrf_decode(secret, req.params.get('state'), uid) return either.to_task( uri.fmap(_add_token_response(creds.token_response))) @curry def _add_token_response(data, uri): # Dict -> String -> String # # if oauth has token_response_param, # add the json-encoded token_response from credentials to the uri params # def _add(key): tok = either.with_default('{}', json_.encode(data)) return add_query_param(uri, key, tok) if params.token_response_param is None: return uri else: return _add(params.token_response_param) return (( (Task(_exchange) >> _cache_and) >> _get_redirect).fmap(redirect_to))
return (match(Routes, {HomeR: always(render_home(req, config))})) def render_home(req, config): secret = (Right(config['secret']) if config.has_key('secret') else Left( KeyError('No secret found in config'))) contents = (secret.fmap( lambda s: ("<h1><a href=\"%s\">Your secret is: %s!</a></h1>" % (encode_path(HomeR()), s)))) return (fold(reject, lambda c: resolve(c).fmap(from_html), contents)) def load_secret(rej, res): try: with open(local_file('secret.json')) as f: res(with_default({}, json_.decode(f.read()))) except Exception as e: rej(err.wrap(e)) main = mount(route_parser, route, init=Task(load_secret)) if __name__ == '__main__': from wsgiref.simple_server import make_server httpd = make_server('', 8080, main) httpd.serve_forever()