diff --git a/controllers/issues.php b/controllers/issues.php index 2f65bc70bff534072acc33aff0fb6ac5367d596a..7c8535a7a74db4526ac5bb02534e02e5b5215845 100644 --- a/controllers/issues.php +++ b/controllers/issues.php @@ -1,8 +1,5 @@ <?php -/** - * @property Parsedown $parsedown - */ -final class IssuesController extends \TracToGitlab\Controller +final class IssuesController extends TracToGitlab\EventController { const SECRET_ISSUE_OPEN = 'N]<d5V/6tn/sYNMy'; @@ -17,35 +14,36 @@ final class IssuesController extends \TracToGitlab\Controller throw new MethodNotAllowedException(); } - if ($_SERVER['HTTP_X_GITLAB_TOKEN'] !== self::SECRET_ISSUE_OPEN) { + if (!$this->verifySecret(self::SECRET_ISSUE_OPEN)) { throw new AccessDeniedException(); } - $input = file_get_contents('php://input'); - $payload = json_decode($input, true); + if ($this->getFromPayload('object_attributes', 'action') === 'open') { + $username = $this->getFromPayload('user', 'username'); + $email = $this->getFromPayload('user', 'email'); - if ($payload['object_attributes']['action'] === 'open') { - $user = User::findOneByUsername($payload['user']['username']) - ?? User::findOneByEmail($payload['user']['email']) + $user = User::findOneByUsername($username) + ?? User::findOneByEmail($email) ?? User::findOneByUsername('gitlab-bot'); if ($user) { + $labels = $this->getFromPayload('labels'); foreach (self::LABEL_MAPPING as $label => $definition) { - if (!$this->hasLabel($payload, $label)) { + if (!$this->hasLabel($labels, $label)) { continue; } $title = sprintf( $definition[2], - $payload['object_attributes']['iid'], - $payload['object_attributes']['title'] + $this->getFromPayload('object_attributes', 'iid'), + $this->getFromPayload('object_attributes', 'title') ); $body = Studip\Markup::markAsHtml( $this->parsedown->text( sprintf( "%s\n\n----\nZum [gitlab-Issue #%u](%s)", - trim($payload['object_attributes']['description']), - $payload['object_attributes']['iid'], - $payload['object_attributes']['url'] + $this->getFromPayload('object_attributes', 'description'), + $this->getFromPayload('object_attributes', 'iid'), + $this->getFromPayload('object_attributes', 'url') ) ) ); @@ -59,18 +57,19 @@ final class IssuesController extends \TracToGitlab\Controller ); $this->gitlab->issues()->addNote( - $payload['project']['id'], - $payload['object_attributes']['iid'], + $this->getFromPayload('project', 'id'), + $this->getFromPayload('object_attributes', 'iid'), "[Zum Forenbeitrag auf dem Entwicklungsserver]({$url})" - ); } + ); + } } } $this->render_nothing(); } - private function hasLabel(array $change, string $needle): bool + private function hasLabel(array $labels, string $needle): bool { - foreach ($change['labels'] as $label) { + foreach ($labels as $label) { if ($label['title'] === $needle) { return true; } diff --git a/controllers/users.php b/controllers/users.php new file mode 100644 index 0000000000000000000000000000000000000000..4e988bee91e2e3d29c69e835bc52317328cca018 --- /dev/null +++ b/controllers/users.php @@ -0,0 +1,29 @@ +<?php +final class UsersController extends TracToGitlab\EventController +{ + const SECRET_USER_CREATED = 'q<-%Y7Ys>h(@LHgg'; + + public function created_action() + { + if (!Request::isPost()) { + throw new MethodNotAllowedException(); + } + + if ( + !$this->verifySecret(self::SECRET_USER_CREATED) + || !$this->verifyEventType('System Hook') + ) { + throw new AccessDeniedException(); + } + + if ($this->getFromPayload('event_name') === 'user_create') { + $this->gitlab->projects()->addMember( + $this->gitlabProjectId, + $this->getFromPayload('user_id'), + 10 + ); + } + + $this->render_nothing(); + } +} diff --git a/lib/EventController.php b/lib/EventController.php new file mode 100644 index 0000000000000000000000000000000000000000..bfc6d992973179f4e56d3dc1c336a4e3609202c2 --- /dev/null +++ b/lib/EventController.php @@ -0,0 +1,53 @@ +<?php +namespace TracToGitlab; + +abstract class EventController extends Controller +{ + private $payload = null; + + protected function verifySecret(string $secret): bool + { + return $_SERVER['HTTP_X_GITLAB_TOKEN'] === $secret; + } + + protected function verifyEventType(string $type): bool + { + return $_SERVER['HTTP_X_GITLAB_EVENT'] === $type; + } + + protected function getFromPayload(...$keys) + { + if ($this->payload === null) { + $this->payload = $this->getPayloadFromRequest() ?? false; + } + if ($this->payload === false) { + throw new \Exception('No payload detected'); + } + + $result = $this->payload; + foreach ($keys as $key) { + if (!isset($result[$key])) { + throw new \Exception("Invalid payload key {$key}"); + } + + $result = $result[$key]; + } + + return $result; + } + + private function getPayloadFromRequest(): ?array + { + $input =file_get_contents('php://input'); + if (!$input) { + return null; + } + + $payload = json_decode($input, true); + if (!$payload || !is_array($payload)) { + return null; + } + + return $payload; + } +} diff --git a/plugin.manifest b/plugin.manifest index bc90b8c4e25e244b8a1ff10e836f3fb2c172b60e..3fa6aee95693ca11854967d821cd50d1050d62a3 100644 --- a/plugin.manifest +++ b/plugin.manifest @@ -1,5 +1,5 @@ pluginname=Trac to gitlab converter pluginclassname=TracToGitlabPlugin origin=UOL -version=1.1 +version=1.1.1 studipMinVersion=5.0