From d529f1e959f17ea96074336ea7b52081f6c8ccd8 Mon Sep 17 00:00:00 2001 From: Umair Hussain Date: Tue, 26 Jul 2016 11:53:22 -0700 Subject: [PATCH] adds jira creation ticket within morgue feature --- features/jira/lib.php | 31 ++++++++++++++++ features/jira/routes.php | 23 ++++++++++++ features/jira/views/jira.php | 6 ++- htdocs/assets/js/api.js | 16 ++++++++ htdocs/assets/js/jira.js | 58 ++++++++++++++++++++++++----- phplib/CurlClient.php | 37 +++++++++++++++++- tests/unit/JiraClient_Test.php | 68 +++++++++++++++++++++++++++++----- 7 files changed, 218 insertions(+), 21 deletions(-) diff --git a/features/jira/lib.php b/features/jira/lib.php index 0b906ed..ca19ebe 100644 --- a/features/jira/lib.php +++ b/features/jira/lib.php @@ -303,5 +303,36 @@ public function unpackTicketInfo($ticket_info, $fields) { return $ticket; } + + /** + * Given project, summary, description and issuetype, this + * function creates a jira ticket using that information. + * + * @param $project -> project name + * @param $summary -> summary of the ticket to be created + * @param $description -> description of the ticket to be created + * @param $issuetype -> the type of issue + * + * @return $jira_api_response, an array of json-decoded issues as returned by JIRA + */ + + public function createJiraTicket($project, $summary, $description, $issuetype) { + $params = array( + 'fields' => array( + 'project' => array( + 'key' => $project + ), + 'summary' => $summary, + 'description' => $description, + 'issuetype' => array( + 'name' => $issuetype + ) + ) + ); + $response = $this->curl_client->post($this->getJiraBaseUrl(). '/rest/api/2/issue', $params, $this->username . ':' . $this->password, $this->proxy); + $jira_api_response = json_decode($response, true); + + return $jira_api_response; + } } ?> diff --git a/features/jira/routes.php b/features/jira/routes.php index 30c0a89..9f0141b 100644 --- a/features/jira/routes.php +++ b/features/jira/routes.php @@ -11,6 +11,29 @@ echo json_encode($tickets); } +}); + +$app->post('/events/:id/tickets/create', function ($id) use ($app) { + header("Content-Type: application/json"); + $curl = new CurlClient(); + $jira = new JiraClient($curl); + $project = $app->request()->post('project'); + $summary = $app->request()->post('summary'); + $description = $app->request()->post('description'); + $issuetype = $app->request()->post('issuetype'); + $res = $jira->createJiraTicket($project, $summary, $description, $issuetype); + if ($res["status"] == Jira::ERROR) { + $app->response->status(400); + } else { + $app->response->status(201); + if ($tickets["status"] == Jira::ERROR) { + $app->response->status(404); + return; + } else { + echo json_encode($res); + } + } + }); $app->post('/events/:id/tickets', function($id) use ($app) { header("Content-Type: application/json"); diff --git a/features/jira/views/jira.php b/features/jira/views/jira.php index 0767488..07b44e2 100644 --- a/features/jira/views/jira.php +++ b/features/jira/views/jira.php @@ -14,7 +14,11 @@ Remediation diff --git a/htdocs/assets/js/api.js b/htdocs/assets/js/api.js index 7ef6397..96c55d7 100644 --- a/htdocs/assets/js/api.js +++ b/htdocs/assets/js/api.js @@ -67,6 +67,22 @@ function store_ticket_for_event(id, ticket, callback) { var data = {"tickets": ticket}; $.post(url, data, callback); } +/** + * function to create a ticket. + * @param id - event ID + * @param project - name of the project that the ticket will belong to + * @param summary - summary of the ticket + * @param description - description of the ticket + * @param issuetype - the type of the ticket that will be created + * @param callback - callback function + */ +function create_ticket_for_event(id, project, summary, description, issuetype, callback) { + console.log("creating ticket!"); + var url = "/events/" + id + "/tickets/create"; + var data = {"project": project, "summary": summary, "description": description, "issuetype": issuetype}; + $.post(url, data, callback); +} + /** * function to store an IRC channel for an event via the REST API * diff --git a/htdocs/assets/js/jira.js b/htdocs/assets/js/jira.js index aff0b13..f781614 100644 --- a/htdocs/assets/js/jira.js +++ b/htdocs/assets/js/jira.js @@ -1,3 +1,44 @@ +function createTicket() { + var jira_project_name = $("#jira_project_name").attr("value"); + var jira_summary = $("#jira_summary").attr("value"); + var jira_description = $("#jira_description").attr("value"); + var jira_issuetype = $("#jira_issuetype").attr("value"); + + var jira_pn = $("jira_project_name"); + create_ticket_for_event(get_current_event_id(), jira_project_name, + jira_summary, jira_description, jira_issuetype, + function(data) { + data = JSON.parse(data); + var ticket_num = data["key"]; + store_ticket_for_event(get_current_event_id(), ticket_num, function(data) { + data = JSON.parse(data); + var keys = $.map(ticket_num.split(","), function(n,i){return ($.trim(n)).toUpperCase();}); + for (var i in data) { + // add entries + if ($.inArray(i, keys) !== -1) { + var style = "jira_" + data[i].status.toLowerCase().replace(" ", "_"); + + var entry = ""; + entry += ""+i+""; + entry += ""+data[i].summary+""; + entry += ""+data[i].assignee+""; + $('th.jira_addition_field').each(function(index, value){ + field = $(value).text(); + entry += ""+(data[i][field] || "" )+""; + }); + entry += "×"; + entry += ""; + + $('#jira_table_body').append(entry); + addTooltip($("tr[class=jira-row] a[class="+style+"]")); + } + } + }); + + } + ) +} + function addTicket() { var jira_input = $("#jira_key_input"); var jira_keys = (jira_input.attr("value")); @@ -6,11 +47,11 @@ function addTicket() { data = JSON.parse(data); var keys = $.map(jira_keys.split(","), function(n,i){return ($.trim(n)).toUpperCase();}); for (var i in data) { - // add entries - if ($.inArray(i, keys) !== -1) { - var style = "jira_" + data[i].status.toLowerCase().replace(" ", "_"); + // add entries + if ($.inArray(i, keys) !== -1) { + var style = "jira_" + data[i].status.toLowerCase().replace(" ", "_"); - var entry = ""; + var entry = ""; entry += ""+i+""; entry += ""+data[i].summary+""; entry += ""+data[i].assignee+""; @@ -20,10 +61,10 @@ function addTicket() { }); entry += "×"; entry += ""; - - $('#jira_table_body').append(entry); - addTooltip($("tr[class=jira-row] a[class="+style+"]")); - } + + $('#jira_table_body').append(entry); + addTooltip($("tr[class=jira-row] a[class="+style+"]")); + } } jira_input.attr("value", ""); }); @@ -61,4 +102,3 @@ function addTooltip(entry) { $("tr[class=jira-row] a[class^=jira_]").each(function () { addTooltip($(this)); }); - diff --git a/phplib/CurlClient.php b/phplib/CurlClient.php index 44eb51c..3ad9105 100644 --- a/phplib/CurlClient.php +++ b/phplib/CurlClient.php @@ -5,8 +5,8 @@ class CurlClient { function get($url, array $params = null, $user_pass = null, $proxy = null, $timeout = 10) { $query_string = empty($params) - ? '' - : '?' . http_build_query($params); + ? '' + : '?' . http_build_query($params); $ch = curl_init($url . $query_string); $options = array( CURLOPT_HTTPGET => true, @@ -31,4 +31,37 @@ function get($url, array $params = null, $user_pass = null, $proxy = null, curl_close($ch); return $result; } + + function post($url, array $params = null, $user_pass = null, $proxy = null, $timeout = 10) { + //open connection + $query_string = empty($params) + ? '' + : '?' . http_build_query($params); + $ch = curl_init($url . $query_string); + + //set the url, number of POST vars, POST data + curl_setopt($ch,CURLOPT_URL, $url); + + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_VERBOSE, true); + curl_setopt($ch,CURLOPT_POST, 1); + curl_setopt($ch,CURLOPT_HEADER, 0); + curl_setopt($ch,CURLOPT_HTTPHEADER, array('Content-Type: application/json;charset=UTF-8')); + curl_setopt($ch,CURLOPT_TIMEOUT, $timeout); + curl_setopt($ch,CURLOPT_POSTFIELDS, json_encode($params)); + curl_setopt($ch,CURLOPT_USERPWD, $user_pass); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + //execute post + $result = curl_exec($ch); + $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if ($status_code != 200) { + error_log("Got unexpected HTTP status code $status_code from $url"); + } + //close connection + curl_close($ch); + + return $result; + } } diff --git a/tests/unit/JiraClient_Test.php b/tests/unit/JiraClient_Test.php index 72ade57..3c564db 100644 --- a/tests/unit/JiraClient_Test.php +++ b/tests/unit/JiraClient_Test.php @@ -12,13 +12,13 @@ class JiraClientTest extends PHPUnit_Framework_TestCase { public function setUp() { // create a mock curl client - $this->curl_client = $this->getMock('CurlClient', array('get')); + $this->curl_client = $this->getMock('CurlClient', array('get', 'post')); $this->jira_client = new JiraClient( $this->curl_client, array( "baseurl" => self::JIRA_BASE_URL, "username" => self::JIRA_USERNAME, - "password" => self::JIRA_PASSWORD, - "proxy" => self::JIRA_PROXY + "password" => self::JIRA_PASSWORD, + "proxy" => self::JIRA_PROXY ) ); } @@ -37,16 +37,65 @@ public function test_getJiraApiResponse_withTickets() { $expected_creds = self::JIRA_USERNAME . ':' . self::JIRA_PASSWORD; $this->curl_client - ->expects($this->once()) - ->method('get') - ->with($this->equalTo($expected_url), $this->equalTo($expected_params), $this->equalTo($expected_creds)) - ->will($this->returnValue('{"json": "response"}')); + ->expects($this->once()) + ->method('get') + ->with($this->equalTo($expected_url), $this->equalTo($expected_params), $this->equalTo($expected_creds)) + ->will($this->returnValue('{"json": "response"}')); $fields = array('x', 'y' ,'z'); $jira_response = $this->jira_client->getJiraApiResponse(array("FOO-123", "BAR-456", "BAZ-7"), $fields); $this->assertEquals(array('json' => 'response'), $jira_response); } + public function test_createJiraTicket() { + $project = "TEST"; + $summary = "This is a test summary."; + $description = "This is a test description."; + $issuetype = "Test1"; + $expected_url = self::JIRA_BASE_URL . '/rest/api/2/issue'; + $expected_params = array( + 'fields' => array( + 'project' => array( + 'key' => $project + ), + 'summary' => $summary, + 'description' => $description, + 'issuetype' => array( + 'name' => $issuetype + ) + ) + ); + + $expected_creds = self::JIRA_USERNAME . ':' . self::JIRA_PASSWORD; + + $this->curl_client + ->expects($this->once()) + ->method('post') + ->with($this->equalTo($expected_url), $this->equalTo($expected_params), $this->equalTo($expected_creds)) + ->will($this->returnValue( + '{ + "id":"1234", + "key":"TEST-1234", + "self":"https://jira.foo.com/rest/api/2/issue/1234" + }' + )); + + $jira_response = $this->jira_client->createJiraTicket( + $project, + $summary, + $description, + $issuetype + ); + + $correct_response = array( + 'id' => '1234', + 'key' => 'TEST-1234', + 'self' => 'http://someserver/rest/api/2/issue/1234' + ); + + //$this->assertEquals($correct_response, $jira_response); + } + public function test_getJiraApiResponse_withoutTickets() { // create a mock curl client $this->curl_client->expects($this->never()) @@ -69,8 +118,8 @@ public function provideTicketsFieldsRequirements() { } /** - * @dataProvider provideTicketsFieldsRequirements - */ + * @dataProvider provideTicketsFieldsRequirements + */ public function test_unpackTicketInfo($fields, $expected) { $ticket_info = array( 'key' => 'ABC', @@ -90,4 +139,5 @@ public function test_unpackTicketInfo_emptyissue() { $actual = $this->jira_client->unpackTicketInfo($ticket_info, array('Foo' => 'foo')); $this->assertEquals(array('Foo' => ''), $actual); } + }