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:
parent
386dcfff7e
commit
97ea6ea619
12 changed files with 377 additions and 8 deletions
|
@ -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',
|
||||
|
|
|
@ -331,7 +331,9 @@ class AphrontDefaultApplicationConfiguration
|
|||
),
|
||||
|
||||
'/audit/' => array(
|
||||
'$' => 'PhabricatorAuditEditController',
|
||||
'$' => 'PhabricatorAuditListController',
|
||||
'view/(?P<filter>[^/]+)/$' => 'PhabricatorAuditListController',
|
||||
|
||||
'edit/$' => 'PhabricatorAuditEditController',
|
||||
),
|
||||
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,5 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorAuditStatusConstants.php');
|
||||
|
|
|
@ -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',
|
||||
));
|
||||
}
|
||||
|
||||
}
|
41
src/applications/audit/controller/list/__init__.php
Normal file
41
src/applications/audit/controller/list/__init__.php
Normal 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');
|
91
src/applications/audit/query/audit/PhabricatorAuditQuery.php
Normal file
91
src/applications/audit/query/audit/PhabricatorAuditQuery.php
Normal 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 '';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
14
src/applications/audit/query/audit/__init__.php
Normal file
14
src/applications/audit/query/audit/__init__.php
Normal 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');
|
102
src/applications/audit/view/list/PhabricatorAuditListView.php
Normal file
102
src/applications/audit/view/list/PhabricatorAuditListView.php
Normal 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();
|
||||
}
|
||||
|
||||
}
|
17
src/applications/audit/view/list/__init__.php
Normal file
17
src/applications/audit/view/list/__init__.php
Normal 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');
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
|
|
Loading…
Reference in a new issue