1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 00:42:41 +01:00

Add a basic first-class audit UI

Summary:
Currently, audits are only accessible through the Owners tool. Start moving them
to their own first-class tool in preparation for broader audit integration.

  - Lay some infrastructure groundwork (e.g. AuditQuery).
  - Build a basic /audit/ view.
  - Show audits on the commit page in Diffusion.

This has some code duplication with stuff we've already got, but I'll merge
everything together as we move forward on this.

Test Plan: Looked at /audit/ and a commit.

Reviewers: btrahan, jungejason

Reviewed By: btrahan

CC: aran, epriestley

Maniphest Tasks: T904

Differential Revision: https://secure.phabricator.com/D1685
This commit is contained in:
epriestley 2012-02-24 13:02:14 -08:00
parent 386dcfff7e
commit 97ea6ea619
12 changed files with 377 additions and 8 deletions

View file

@ -443,6 +443,9 @@ phutil_register_library_map(array(
'PhabricatorAuditController' => 'applications/audit/controller/base',
'PhabricatorAuditDAO' => 'applications/audit/storage/base',
'PhabricatorAuditEditController' => 'applications/audit/controller/edit',
'PhabricatorAuditListController' => 'applications/audit/controller/list',
'PhabricatorAuditListView' => 'applications/audit/view/list',
'PhabricatorAuditQuery' => 'applications/audit/query/audit',
'PhabricatorAuditStatusConstants' => 'applications/audit/constants/status',
'PhabricatorAuthController' => 'applications/auth/controller/base',
'PhabricatorCalendarBrowseController' => 'applications/calendar/controller/browse',
@ -1216,6 +1219,8 @@ phutil_register_library_map(array(
'PhabricatorAuditController' => 'PhabricatorController',
'PhabricatorAuditDAO' => 'PhabricatorLiskDAO',
'PhabricatorAuditEditController' => 'PhabricatorAuditController',
'PhabricatorAuditListController' => 'PhabricatorAuditController',
'PhabricatorAuditListView' => 'AphrontView',
'PhabricatorAuthController' => 'PhabricatorController',
'PhabricatorCalendarBrowseController' => 'PhabricatorCalendarController',
'PhabricatorCalendarController' => 'PhabricatorController',

View file

@ -331,7 +331,9 @@ class AphrontDefaultApplicationConfiguration
),
'/audit/' => array(
'$' => 'PhabricatorAuditEditController',
'$' => 'PhabricatorAuditListController',
'view/(?P<filter>[^/]+)/$' => 'PhabricatorAuditListController',
'edit/$' => 'PhabricatorAuditEditController',
),

View file

@ -1,7 +1,7 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* limitations under the License.
*/
class PhabricatorAuditStatusConstants {
final class PhabricatorAuditStatusConstants {
const NONE = '';
const AUDIT_NOT_REQUIRED = 'audit-not-required';
@ -26,14 +26,18 @@ class PhabricatorAuditStatusConstants {
public static function getStatusNameMap() {
static $map = array(
self::NONE => 'Not Apply',
self::AUDIT_NOT_REQUIRED => 'Audit Not Required',
self::AUDIT_REQUIRED => 'Audit Required',
self::CONCERNED => 'Concerned',
self::ACCEPTED => 'Accepted',
self::NONE => 'Not Applicable',
self::AUDIT_NOT_REQUIRED => 'Audit Not Required',
self::AUDIT_REQUIRED => 'Audit Required',
self::CONCERNED => 'Concern Raised',
self::ACCEPTED => 'Accepted',
);
return $map;
}
public static function getStatusName($code) {
return idx(self::getStatusNameMap(), $code, 'Unknown');
}
}

View file

@ -6,5 +6,7 @@
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorAuditStatusConstants.php');

View file

@ -0,0 +1,68 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class PhabricatorAuditListController extends PhabricatorAuditController {
private $filter;
public function willProcessRequest(array $data) {
$this->filter = idx($data, 'filter');
}
public function processRequest() {
$request = $this->getRequest();
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI('/audit/view/'));
$nav->addLabel('Audits');
$nav->addFilter('all', 'All');
$this->filter = $nav->selectFilter($this->filter, 'all');
$pager = new AphrontPagerView();
$pager->setURI($request->getRequestURI(), 'offset');
$query = new PhabricatorAuditQuery();
$query->setOffset($pager->getOffset());
$query->setLimit($pager->getPageSize() + 1);
$audits = $query->execute();
$audits = $pager->sliceResults($audits);
$view = new PhabricatorAuditListView();
$view->setAudits($audits);
$phids = $view->getRequiredHandlePHIDs();
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$view->setHandles($handles);
$panel = new AphrontPanelView();
$panel->appendChild($view);
$panel->setHeader('Audits');
$nav->appendChild($panel);
$nav->appendChild($pager);
return $this->buildStandardPageResponse(
$nav,
array(
'title' => 'Audits',
));
}
}

View file

@ -0,0 +1,41 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/404');
phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/audit/constants/action');
phutil_require_module('phabricator', 'applications/audit/constants/status');
phutil_require_module('phabricator', 'applications/audit/controller/base');
phutil_require_module('phabricator', 'applications/audit/query/audit');
phutil_require_module('phabricator', 'applications/audit/storage/auditcomment');
phutil_require_module('phabricator', 'applications/audit/view/list');
phutil_require_module('phabricator', 'applications/differential/storage/revision');
phutil_require_module('phabricator', 'applications/owners/storage/owner');
phutil_require_module('phabricator', 'applications/owners/storage/package');
phutil_require_module('phabricator', 'applications/owners/storage/packagecommitrelationship');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phabricator', 'view/control/pager');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/divider');
phutil_require_module('phabricator', 'view/form/control/markup');
phutil_require_module('phabricator', 'view/form/control/select');
phutil_require_module('phabricator', 'view/form/control/static');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phabricator', 'view/layout/sidenavfilter');
phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'parser/uri');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorAuditListController.php');

View file

@ -0,0 +1,91 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class PhabricatorAuditQuery {
private $offset;
private $limit;
private $commitPHIDs;
public function withCommitPHIDs(array $commit_phids) {
$this->commitPHIDs = $commit_phids;
return $this;
}
public function setOffset($offset) {
$this->offset = $offset;
return $this;
}
public function setLimit($limit) {
$this->limit = $limit;
return $this;
}
public function execute() {
$table = new PhabricatorOwnersPackageCommitRelationship();
$conn_r = $table->establishConnection('r');
$where = $this->buildWhereClause($conn_r);
$limit = $this->buildLimitClause($conn_r);
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q',
$table->getTableName(),
$where,
$limit);
$audits = $table->loadAllFromArray($data);
return $audits;
}
private function buildWhereClause($conn_r) {
$where = array();
if ($this->commitPHIDs) {
$where[] = qsprintf(
$conn_r,
'commitPHID IN (%Ls)',
$this->commitPHIDs);
}
if ($where) {
$where = 'WHERE ('.implode(') AND (', $where).')';
} else {
$where = '';
}
return $where;
}
private function buildLimitClause($conn_r) {
if ($this->limit && $this->offset) {
return qsprintf($conn_r, 'LIMIT %d, %d', $this->offset, $this->limit);
} else if ($this->limit) {
return qsprintf($conn_r, 'LIMIT %d', $this->limit);
} else if ($this->offset) {
return qsprintf($conn_r, 'LIMIT %d, %d', $this->offset, PHP_INT_MAX);
} else {
return '';
}
}
}

View file

@ -0,0 +1,14 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/owners/storage/packagecommitrelationship');
phutil_require_module('phabricator', 'storage/qsprintf');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_source('PhabricatorAuditQuery.php');

View file

@ -0,0 +1,102 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class PhabricatorAuditListView extends AphrontView {
private $audits;
private $handles;
public function setAudits(array $audits) {
$this->audits = $audits;
return $this;
}
public function setHandles(array $handles) {
$this->handles = $handles;
return $this;
}
public function getRequiredHandlePHIDs() {
$phids = array();
foreach ($this->audits as $audit) {
$phids[$audit->getCommitPHID()] = true;
$phids[$audit->getPackagePHID()] = true;
}
return array_keys($phids);
}
private function getHandle($phid) {
$handle = idx($this->handles, $phid);
if (!$handle) {
throw new Exception("No handle for '{$phid}'!");
}
return $handle;
}
public function render() {
$last = null;
$rows = array();
foreach ($this->audits as $audit) {
$commit_phid = $audit->getCommitPHID();
if ($last == $commit_phid) {
$commit_name = null;
} else {
$commit_name = $this->getHandle($commit_phid)->renderLink();
$last = $commit_phid;
}
$reasons = $audit->getAuditReasons();
foreach ($reasons as $key => $reason) {
$reasons[$key] = phutil_escape_html($reason);
}
$reasons = implode('<br />', $reasons);
$status_code = $audit->getAuditStatus();
$status = PhabricatorAuditStatusConstants::getStatusName($status_code);
$auditor_handle = $this->getHandle($audit->getPackagePHID());
$rows[] = array(
$commit_name,
$auditor_handle->renderLink(),
phutil_escape_html($status),
$reasons,
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
'Commit',
'Auditor',
'Status',
'Details',
));
$table->setColumnClasses(
array(
'pri',
'',
'',
'wide',
));
return $table->render();
}
}

View file

@ -0,0 +1,17 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/audit/constants/status');
phutil_require_module('phabricator', 'view/base');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorAuditListView.php');

View file

@ -86,6 +86,8 @@ class DiffusionCommitController extends DiffusionController {
$content[] = $detail_panel;
}
$content[] = $this->buildAuditTable($commit);
$change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
$drequest);
$changes = $change_query->loadChanges();
@ -290,4 +292,23 @@ class DiffusionCommitController extends DiffusionController {
'</table>';
}
private function buildAuditTable($commit) {
$query = new PhabricatorAuditQuery();
$query->withCommitPHIDs(array($commit->getPHID()));
$audits = $query->execute();
$view = new PhabricatorAuditListView();
$view->setAudits($audits);
$phids = $view->getRequiredHandlePHIDs();
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$view->setHandles($handles);
$panel = new AphrontPanelView();
$panel->setHeader('Audits');
$panel->appendChild($view);
return $panel;
}
}

View file

@ -6,6 +6,8 @@
phutil_require_module('phabricator', 'applications/audit/query/audit');
phutil_require_module('phabricator', 'applications/audit/view/list');
phutil_require_module('phabricator', 'applications/differential/constants/changetype');
phutil_require_module('phabricator', 'applications/differential/view/changesetlistview');
phutil_require_module('phabricator', 'applications/diffusion/controller/base');