From: Michael Wallner Date: Mon, 4 May 2015 16:02:09 +0000 (+0200) Subject: webhook management X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=930d06a96fa24317f053fecb8569aacaa69a0778;p=pharext%2Fpharext.org webhook management --- diff --git a/app/Cli.php b/app/Cli.php new file mode 100644 index 0000000..114bfed --- /dev/null +++ b/app/Cli.php @@ -0,0 +1,114 @@ +config = $config; + $this->args = $args; + } + + function __invoke($argc, array $argv) { + $prog = array_shift($argv); + foreach ($this->args->parse(--$argc, $argv) as $error) { + $errs[] = $error; + } + + if ($this->args["help"] || !array_filter($this->args->toArray())) { + $this->help($prog); + exit; + } + if (!empty($errs)) { + foreach ($errs as $err) { + fprintf(STDERR, "ERROR: %s\n", $err); + exit(-1); + } + } + + if ($this->args["ngrok"]) { + system($this->config->ngrok->command . " ". implode(" ", array_map("escapeshellarg", [ + "http", + "--subdomain=pharext", + "--authtoken", + $this->config->ngrok->auth->token, + "--auth", + $this->config->ngrok->auth->user .":". $this->config->ngrok->auth->pass, + "80" + ]))); + } + } + + function getConfig() { + return $this->config; + } + + /** + * Output command line help message + * @param string $prog + */ + public function help($prog) { + printf("Usage:\n\n \$ %s", $prog); + + $flags = []; + $required = []; + $optional = []; + foreach ($this->args->getSpec() as $spec) { + if ($spec[3] & Args::REQARG) { + if ($spec[3] & Args::REQUIRED) { + $required[] = $spec; + } else { + $optional[] = $spec; + } + } else { + $flags[] = $spec; + } + } + + if ($flags) { + printf(" [-%s]", implode("", array_column($flags, 0))); + } + foreach ($required as $req) { + printf(" -%s ", $req[0]); + } + if ($optional) { + printf(" [-%s ]", implode("|-", array_column($optional, 0))); + } + printf("\n\n"); + $spc = $this->args->getSpec(); + $max = $spc ? max(array_map("strlen", array_column($spc, 1))) : 0; + $max += $max % 8 + 2; + foreach ($spc as $spec) { + if (isset($spec[0])) { + printf(" -%s|", $spec[0]); + } else { + printf(" "); + } + printf("--%s ", $spec[1]); + if ($spec[3] & Args::REQARG) { + printf(" "); + } elseif ($spec[3] & Args::OPTARG) { + printf("[]"); + } else { + printf(" "); + } + printf("%s%s", str_repeat(" ", $max-strlen($spec[1])+3*!isset($spec[0])), $spec[2]); + if ($spec[3] & Args::REQUIRED) { + printf(" (REQUIRED)"); + } + if (isset($spec[4])) { + printf(" [%s]", $spec[4]); + } + printf("\n"); + } + printf("\n"); + } +} diff --git a/app/Controller/Github/Hook.php b/app/Controller/Github/Hook.php new file mode 100644 index 0000000..946bb0c --- /dev/null +++ b/app/Controller/Github/Hook.php @@ -0,0 +1,35 @@ +app = $app; + $this->github = $github; + } + + function __invoke(array $args = []) { + $request = $this->app->getRequest(); + $response = $this->app->getResponse(); + + if (!($sig = $request->getHeader("X-Github-Signature")) || !($evt = $request->getHeader("X-Github-Event"))) { + $response->setResponseCode(400); + } elseif ($sig !== hash_hmac("sha1", $request->getBody(), $this->app->getConfig()->github->client->secret)) { + $response->setResponseCode(403); + } elseif ($evt === "ping") { + $response->setReponseStatus("PONG"); + } elseif ($evt !== "push") { + $this->app->getResponse()->setResponseCode(204); + } else { + $push = json_decode($request->getBody()); + } + } +} diff --git a/app/Controller/Github/Repo.php b/app/Controller/Github/Repo.php index 2ee935d..f194d8e 100644 --- a/app/Controller/Github/Repo.php +++ b/app/Controller/Github/Repo.php @@ -17,6 +17,13 @@ class Repo extends Github } catch (\app\Github\Exception $exception) { $this->app->getView()->addData(compact("exception", "owner", "name")); } + + if (($modal = $this->app->getRequest()->getQuery("modal"))) { + $this->app->getView()->addData(compact("modal") + [ + "action" => $this->app->getRequest()->getQuery($modal) + ]); + } + $this->app->display("github/repo"); } } diff --git a/app/Controller/Github/Repo/Hook.php b/app/Controller/Github/Repo/Hook.php index 7bfb545..1ef33a3 100644 --- a/app/Controller/Github/Repo/Hook.php +++ b/app/Controller/Github/Repo/Hook.php @@ -7,14 +7,22 @@ use app\Controller\Github; class Hook extends Github { function __invoke(array $args = null) { - switch ($args["action"]) { - case "add": - $this->addHook($args["owner"], $args["name"]); - break; - - case "del": - $this->delHook($args["owner"], $args["name"]); - break; + if ($this->checkToken()) { + if ($this->app->getRequest()->getRequestMethod() != "POST") { + // user had to re-authenticate, and was redirected here + $this->app->redirect($this->app->getBaseUrl()->mod([ + "path" => "./github/repo/" . $args["owner"] ."/". $args["name"], + "query" => "modal=hook&hook=" . $args["action"] + ])); + } else switch ($args["action"]) { + case "add": + $this->addHook($args["owner"], $args["name"]); + break; + + case "del": + $this->delHook($args["owner"], $args["name"]); + break; + } } } diff --git a/app/Github/Create/Webhook.php b/app/Github/Create/Webhook.php index 6e583fc..76765e8 100644 --- a/app/Github/Create/Webhook.php +++ b/app/Github/Create/Webhook.php @@ -20,8 +20,8 @@ class Webhook extends Create "config" => [ "url" => $this->config->hook->url, "content_type" => $this->config->hook->content_type, + "insecure_ssl" => $this->config->hook->insecure_ssl, "secret" => $this->config->client->secret, // FIXME: bad idea? - "insecure_ssl" => false, ] ])); return $request; diff --git a/app/Web.php b/app/Web.php index 39cfe8d..c9659b6 100644 --- a/app/Web.php +++ b/app/Web.php @@ -2,7 +2,6 @@ namespace app; -use http\Url; use http\Env\Request; use http\Env\Response; diff --git a/app/bootstrap/cli.php b/app/bootstrap/cli.php new file mode 100644 index 0000000..4a0239e --- /dev/null +++ b/app/bootstrap/cli.php @@ -0,0 +1,20 @@ +share(Cli::class); + +$injector->share(Args::class) + ->define(Args::class, [ + ":spec" => [ + [null, "ngrok", "Run ngrok", Args::SINGLE], + ["h", "help", "Show this help", Args::HALT], + ] + ]); diff --git a/app/config.ini b/app/config.ini index 22dd591..a88c395 100644 --- a/app/config.ini +++ b/app/config.ini @@ -1,6 +1,8 @@ [production] github.hook.url = https://pharext.org/github/hook +github.hook.content_type = json +github.hook.insecure_ssl = 0 github.fetch.repos.per_page = 10 github.fetch.hooks.per_page = 100 @@ -22,3 +24,8 @@ session.cache_limiter = private_no_expire session.cache_expire = 0 [localhost : production] + +github.hook.url = https://pharext.ngrok.io/src/pharext.org.git/public/github/hook +github.hook.insecure_ssl = 1 + +ngrok.command = ngrok \ No newline at end of file diff --git a/app/routes.ini b/app/routes.ini index 40782bf..ad01201 100644 --- a/app/routes.ini +++ b/app/routes.ini @@ -7,6 +7,9 @@ GET[] = /pages/{page} [Github\Callback] GET[] = /github/callback +[Github\Hook] +POST[] = /github/hook + [Github\Index] GET[] = /github @@ -16,6 +19,8 @@ GET[] = /github/repo/{owner}/{name}/{page} [Github\Repo\Hook] POST[] = /github/repo/{owner}/{name}/hook/{action} +; if the user has to re-authenticate, we'll receive a GET because of a redirect +GET[] = /github/repo/{owner}/{name}/hook/{action} [Github\Signin] GET[] = /github/signin diff --git a/app/views/layout.phtml b/app/views/layout.phtml index 98597ef..383ae22 100644 --- a/app/views/layout.phtml +++ b/app/views/layout.phtml @@ -37,6 +37,9 @@ section("content") ?> + + fetch("modal/$modal") ?> +

@@ -53,7 +56,7 @@

- + diff --git a/app/views/modal/hook.phtml b/app/views/modal/hook.phtml new file mode 100644 index 0000000..6a6df0d --- /dev/null +++ b/app/views/modal/hook.phtml @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/bin/pharext.org b/bin/pharext.org new file mode 100755 index 0000000..8937568 --- /dev/null +++ b/bin/pharext.org @@ -0,0 +1,8 @@ +#!/usr/bin/php +execute(Cli::class, [$argc, $argv]); diff --git a/composer.json b/composer.json index 573d1d9..c8914d0 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ }], "autoload": { "psr-0": { - "app": "" + "app": "", + "pharext": "vendor/m6w6/pharext/src" } }, "require": {