def post(self): """Sign the owner out and return to given return page.""" # XXX if not web.tx.user.is_owner: # XXX raise web.Unauthorized("must be owner") web.tx.user.session = None return_to = web.form(return_to="").return_to raise web.SeeOther(f"/{return_to}")
def post(self): program = web.form("program").program machine = tx.db.select("machines", where="name = ?", vals=[self.machine])[0] web.enqueue(build, machine["ip_address"], program) raise web.Accepted(f"{program} is building on the machine..")
def initiate_auth(): """ Begin the authorization and return a three-tuple of client, developer and scope(s). Should be called from the GET handler for the Authorization Endpoint. """ form = web.form("response_type", "client_id", "redirect_uri", "state", scope="") if form.response_type not in ("code", "id"): # NOTE `id` for backcompat raise web.BadRequest('`response_type` must be "code".') client, developer = _discover_client(form.client_id) tx.user.session.update( client_id=form.client_id, client_name=client["name"], redirect_uri=form.redirect_uri, state=form.state, ) if "code_challenge" in form and "code_challenge_method" in form: tx.user.session.update( code_challenge=form.code_challenge, code_challenge_method=form.code_challenge_method, ) return client, developer, form.scope.split()
def post(self): """Perform an action.""" form = web.form("action", channel="default") response = {} if form.action == "channels": web.tx.sub.add_channel(form.name) response = {"channels": web.tx.sub.get_channels()} elif form.action == "search": response = {"results": web.tx.sub.search(form.query)} elif form.action == "preview": response = web.tx.sub.preview(form.url) elif form.action == "follow": web.tx.sub.follow(form.url) response = {"items": web.tx.sub.get_following()} web.enqueue(websub.subscribe, f"{web.tx.origin}/subscriptions/sent", form.url) elif form.action == "unfollow": pass elif form.action == "timeline": pass elif form.action == "mute": pass elif form.action == "unmute": pass elif form.action == "block": pass elif form.action == "unblock": pass web.header("Content-Type", "application/json") return response
def post(self): name = web.form("name").name token = tx.db.select("providers", where="service = ?", vals=["dynadot.com"])[0]["token"] # XXX web.enqueue(spawn_machine, name, token) raise web.Created("domain has been added..", f"/sites/domains/{name}")
def post(self): name = web.form("name").name token = tx.db.select("providers", where="service = ?", vals=["digitalocean.com"])[0]["token"] web.enqueue(spawn_machine, name, token) raise web.Accepted("machine is being created..")
def get(self): """Return a search box or search results.""" try: query = web.form("q").q except web.BadRequest: return app.view.search() results = tx.cache.search(query) return app.view.results(query, results)
def post(self): """Handle "Access Token" flow response or revoke an existing access token.""" # TODO token introspection # TODO token verification try: form = web.form("action", "token") except web.BadRequest: return _redeem_authorization_code("token") if form.action == "revoke": revoke_auth(form.token)
def post(self): try: topic_url = web.form("topic_url").topic_url except web.BadRequest: pass else: web.enqueue(websub.subscribe, f"{web.tx.origin}/subscriptions/sent", topic_url) return app.view.sent.subscription_requested() mode = web.form("hub.mode")["hub.mode"] if mode != "subscribe": raise web.BadRequest( 'hub only supports subscription; `hub.mode` must be "subscribe"' ) form = web.form("hub.topic", "hub.callback") # TODO raise web.BadRequest("topic not found") web.enqueue(websub.verify_received_subscription, form["hub.topic"], form["hub.callback"]) raise web.Accepted("subscription request accepted")
def verify_passphrase(self): """Verify passphrase, sign the owner in and return to given return page.""" form = web.form("passphrase", return_to="/") passphrase = web.tx.identities.get_passphrase() if web.verify_passphrase( passphrase["passphrase_salt"], passphrase["passphrase_hash"], form.passphrase.replace(" ", ""), ): web.tx.user.session = web.tx.identities.get_identity( web.tx.origin)["card"] raise web.SeeOther(form.return_to) raise web.Unauthorized("bad passphrase")
def redeem_authorization_code(flow: str, me: web.uri, name: str = None, email: str = None, photo: web.uri = None) -> dict: """ Redeem an authorization code with given `flow` and return a profile and/or a token. `flow` can be one of ['profile'][0] or ['token'][1]. [0]: https://indieauth.spec.indieweb.org/#profile-url-response [1]: https://indieauth.spec.indieweb.org/#access-token-response """ form = web.form("code", "client_id", "redirect_uri", grant_type="authorization_code") # TODO verify authenticity # TODO grant_type=refresh_token if form.grant_type not in ("authorization_code", "refresh_token"): raise web.Forbidden(f"`grant_type` {form.grant_type} not supported") auth = tx.auth_server.get_auth_from_code(form.code) if form.client_id != auth["client_id"]: raise web.BadRequest("`client_id` does not match original request") if form.redirect_uri != auth["redirect_uri"]: raise web.BadRequest("`redirect_uri` does not match original request") if "code_verifier" in form: if not auth["code_challenge"]: raise web.BadRequest("`code_verifier` without a `code_challenge`") if auth["code_challenge"] != generate_challenge(form.code_verifier): raise web.Forbidden("code mismatch") elif auth["code_challenge"]: raise web.BadRequest("`code_challenge` without `code_verifier`") response = auth["response"] if flow == "token": if not response["scope"]: raise web.BadRequest("Access Token request requires a scope") response.update( token_type="Bearer", access_token=f"secret-token:{web.nbrandom(24)}", ) response["me"] = me if "profile" in response["scope"]: response["profile"] = {"url": me, "name": name, "photo": photo} if "email" in response["scope"] and email: response["profile"]["email"] = email tx.auth_server.update_auth(response, auth["code"]) web.header("Content-Type", "application/json") return response
def wrap(handler, main_app): """Ensure an owner exists and then add their details to the transaction.""" web.tx.response.claimed = True try: web.tx.host.owner = web.tx.identities.get_identity( web.tx.origin)["card"] except IndexError: web.header("Content-Type", "text/html") # if web.tx.request.method == "GET": # web.tx.response.claimed = False # raise web.NotFound(app.view.claim()) # elif web.tx.request.method == "POST": # name = web.form("name").name web.tx.identities.add_identity(web.tx.origin, "Anonymous") passphrase = " ".join(web.tx.identities.add_passphrase()) web.tx.host.owner = web.tx.user.session = web.tx.identities.get_identity( web.tx.origin)["card"] web.tx.user.is_owner = True if kiosk := web.form(kiosk=None).kiosk: with open(f"{kiosk}/passphrase", "w") as fp: fp.write(passphrase) raise web.SeeOther("/") raise web.Created(app.view.claimed(web.tx.origin, passphrase), web.tx.origin)
def get(self): """Confirm subscription request.""" try: action = web.form("action").action except web.BadRequest: pass else: if action == "unsubscribe": web.enqueue(websub.unsubscribe, self.subscription_id) return "unsubscribed" raise web.BadRequest("action must be `unsubscribe`") try: form = web.form("hub.mode", "hub.topic", "hub.challenge", "hub.lease_seconds") except web.BadRequest: pass else: web.tx.websub.verify_sent_subscription( form["hub.topic"], f"{web.tx.origin}/subscriptions/sent/{self.subscription_id}", ) # TODO verify the subscription return form["hub.challenge"] return "sent sub"
def get(self): """Perform an action or return an activity summary.""" try: form = web.form("action", channel="default") except web.BadRequest: return app.view.activity(web.tx.sub.get_following(), web.tx.sub.get_channels()) response = {} if form.action == "channels": response = {"channels": web.tx.sub.get_channels()} if form.action == "follow": response = {"items": web.tx.sub.get_following()} elif form.action == "timeline": response = {"items": []} web.header("Content-Type", "application/json") return response
def post(self): tx.db.update("config", theme=web.form("action").action == "activate") return "accepted"
def post(self): # form = web.form("subdomain", "name") form = web.form("provider", "token") config = get_config() # domain = config["domain"] # fqdn = domain # if form.subdomain: # fqdn = f"{form.subdomain}.{domain}" # update_config(fqdn=fqdn) if form.provider == "digitalocean.com": c = host.digitalocean.Client(form.token) try: c.get_keys() except host.digitalocean.TokenError: return {"status": "error", "message": "bad token"} elif form.provider == "linode.com": ... elif form.provider == "hetzner.com": ... else: return { "status": "error", "message": f"unsupported provider: {form.provider}", } config = update_config(host={ "provider": form.provider, "token": form.token, }) # try: # ip_address = config["ip_address"] # except KeyError: ip_address = host.spawn_machine("canopy", config["host"]["token"]) config = update_config(ipAddress=ip_address, status={}) # registrar = config["registrar"] # if registrar["provider"] == "dynadot.com": # dynadot = host.providers.Dynadot(registrar["token"]) # dynadot.create_record(domain, ip_address, form.subdomain) # elif registrar["provider"] == "name.com": # namecom = host.providers.NameCom(registrar["username"], # registrar["token"]) # namecom.create_record(domain, ip_address, form.subdomain) host.setup_machine(ip_address) config = update_config(system_setup=True) host.setup_nginx(ip_address) config = update_config(nginx_installed=True) return host.generate_dhparam(ip_address) host.setup_tor(ip_address) host.setup_python(ip_address) host.setup_supervisor(ip_address) # while True: # try: # if web.dns.resolve(fqdn, "A")[0].address == ip_address: # break # except ( # web.dns.NoAnswer, # web.dns.NXDOMAIN, # web.dns.Timeout, # web.dns.NoNameservers, # ): # pass # else: # print("waiting for DNS changes to propagate..") # time.sleep(15) onion, passphrase = setup_canopy(ip_address) # , form.name, fqdn) update_config(onion=onion, passphrase=passphrase) return {"onion": onion, "passphrase": passphrase}
def post(self): """Handle consent screen action.""" form = web.form("action", scopes=[]) if form.action == "cancel": raise web.SeeOther(tx.user.session["redirect_uri"]) consent(form.scopes)
def post(self): """""" form = web.form("source", "target") web.enqueue(receive, form.source, form.target) raise web.Accepted("webmention received")
def post(self): form = web.form("service", "token") web.tx.db.insert("providers", service=form.service, token=form.token) return "token has been set"
def get(self): """Return a preview of given `url`.""" form = web.form("url") return app.view.preview(form.url, web.tx.sub.preview(form.url), web.tx.sub.get_channels())
def get(self): """Return search results for given `q`.""" form = web.form("q") return app.view.search(form.q, web.tx.sub.search(form.q))