mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 21:02:41 +01:00
Enable admin to view and delete other users' herald rules
Summary: enable admin to delete user's herald rules. This is useful for managing non-active users' rules. For example, ex-employees' rules. The code change includes: - Added a 'All' tab which is only accessible to admin. - Refactor out a HeraldRuleListView which is used by both the home controller and the all rule controller Test Plan: delete an ex-employee rule as an admin; disable myself as admin and verified that I don't have access to view other user's rules and I'am not be able to delete them; also verified that as a non-admin, I can still view, create and delete my own rules. Reviewers: epriestley, nh Reviewed By: epriestley CC: aran, epriestley, jungejason Differential Revision: 1064
This commit is contained in:
parent
ae1f52642c
commit
42383214ea
11 changed files with 363 additions and 81 deletions
|
@ -293,6 +293,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionView' => 'applications/diffusion/view/base',
|
||||
'HeraldAction' => 'applications/herald/storage/action',
|
||||
'HeraldActionConfig' => 'applications/herald/config/action',
|
||||
'HeraldAllRulesController' => 'applications/herald/controller/all',
|
||||
'HeraldApplyTranscript' => 'applications/herald/storage/transcript/apply',
|
||||
'HeraldCommitAdapter' => 'applications/herald/adapter/commit',
|
||||
'HeraldCondition' => 'applications/herald/storage/condition',
|
||||
|
@ -317,6 +318,7 @@ phutil_register_library_map(array(
|
|||
'HeraldRepetitionPolicyConfig' => 'applications/herald/config/repetitionpolicy',
|
||||
'HeraldRule' => 'applications/herald/storage/rule',
|
||||
'HeraldRuleController' => 'applications/herald/controller/rule',
|
||||
'HeraldRuleListView' => 'applications/herald/view/rulelist',
|
||||
'HeraldRuleTranscript' => 'applications/herald/storage/transcript/rule',
|
||||
'HeraldTestConsoleController' => 'applications/herald/controller/test',
|
||||
'HeraldTranscript' => 'applications/herald/storage/transcript/base',
|
||||
|
@ -974,6 +976,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionSymbolController' => 'DiffusionController',
|
||||
'DiffusionView' => 'AphrontView',
|
||||
'HeraldAction' => 'HeraldDAO',
|
||||
'HeraldAllRulesController' => 'HeraldController',
|
||||
'HeraldApplyTranscript' => 'HeraldDAO',
|
||||
'HeraldCommitAdapter' => 'HeraldObjectAdapter',
|
||||
'HeraldCondition' => 'HeraldDAO',
|
||||
|
@ -986,6 +989,7 @@ phutil_register_library_map(array(
|
|||
'HeraldNewController' => 'HeraldController',
|
||||
'HeraldRule' => 'HeraldDAO',
|
||||
'HeraldRuleController' => 'HeraldController',
|
||||
'HeraldRuleListView' => 'AphrontView',
|
||||
'HeraldTestConsoleController' => 'HeraldController',
|
||||
'HeraldTranscript' => 'HeraldDAO',
|
||||
'HeraldTranscriptController' => 'HeraldController',
|
||||
|
|
|
@ -274,6 +274,10 @@ class AphrontDefaultApplicationConfiguration
|
|||
'rule/(?:(?P<id>\d+)/)?$' => 'HeraldRuleController',
|
||||
'delete/(?P<id>\d+)/$' => 'HeraldDeleteController',
|
||||
'test/$' => 'HeraldTestConsoleController',
|
||||
'all/' => array(
|
||||
'$' => 'HeraldAllRulesController',
|
||||
'view/(?P<view>[^/]+)/$' => 'HeraldAllRulesController',
|
||||
),
|
||||
'transcript/$' => 'HeraldTranscriptListController',
|
||||
'transcript/(?P<id>\d+)/(?:(?P<filter>\w+)/)?$'
|
||||
=> 'HeraldTranscriptController',
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
*/
|
||||
|
||||
class HeraldAllRulesController extends HeraldController {
|
||||
|
||||
private $view;
|
||||
private $viewPHID;
|
||||
|
||||
public function shouldRequireAdmin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->view = idx($data, 'view');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
$this->viewPHID = nonempty($request->getStr('phid'), null);
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$phid_arr = $request->getArr('view_user');
|
||||
$view_target = head($phid_arr);
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($request->getRequestURI()->alter('phid', $view_target));
|
||||
}
|
||||
|
||||
$map = HeraldContentTypeConfig::getContentTypeMap();
|
||||
if (empty($map[$this->view])) {
|
||||
reset($map);
|
||||
$this->view = key($map);
|
||||
}
|
||||
|
||||
$offset = $request->getInt('offset', 0);
|
||||
$pager = new AphrontPagerView();
|
||||
$pager->setPageSize(50);
|
||||
$pager->setOffset($offset);
|
||||
$pager->setURI($request->getRequestURI(), 'offset');
|
||||
|
||||
list($rules, $handles) = $this->queryRules($pager);
|
||||
|
||||
if (!$this->viewPHID) {
|
||||
$view_users = array();
|
||||
} else {
|
||||
$view_users = array(
|
||||
$this->viewPHID => $handles[$this->viewPHID]->getFullName(),
|
||||
);
|
||||
}
|
||||
|
||||
$filter_form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->appendChild(
|
||||
id(new AphrontFormTokenizerControl())
|
||||
->setDatasource('/typeahead/common/users/')
|
||||
->setLabel('View User')
|
||||
->setName('view_user')
|
||||
->setValue($view_users)
|
||||
->setLimit(1));
|
||||
$filter_view = new AphrontListFilterView();
|
||||
$filter_view->appendChild($filter_form);
|
||||
|
||||
$list_view = id(new HeraldRuleListView())
|
||||
->setRules($rules)
|
||||
->setHandles($handles)
|
||||
->setMap($map)
|
||||
->setAllowCreation(false)
|
||||
->setView($this->view);
|
||||
$panel = $list_view->render();
|
||||
$panel->appendChild($pager);
|
||||
|
||||
$sidenav = new AphrontSideNavView();
|
||||
$sidenav->appendChild($filter_view);
|
||||
$sidenav->appendChild($panel);
|
||||
|
||||
$query = '';
|
||||
if ($this->viewPHID) {
|
||||
$query = '?phid='.$this->viewPHID;
|
||||
}
|
||||
|
||||
foreach ($map as $key => $value) {
|
||||
$sidenav->addNavItem(
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/herald/all/view/'.$key.'/'.$query,
|
||||
'class' => ($key == $this->view)
|
||||
? 'aphront-side-nav-selected'
|
||||
: null,
|
||||
),
|
||||
phutil_escape_html($value)));
|
||||
}
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$sidenav,
|
||||
array(
|
||||
'title' => 'Herald',
|
||||
'tab' => 'all',
|
||||
));
|
||||
}
|
||||
|
||||
private function queryRules(AphrontPagerView $pager) {
|
||||
$rule = new HeraldRule();
|
||||
$conn_r = $rule->establishConnection('r');
|
||||
|
||||
$where_clause = qsprintf(
|
||||
$conn_r,
|
||||
'WHERE contentType = %s',
|
||||
$this->view);
|
||||
|
||||
if ($this->viewPHID) {
|
||||
$where_clause .= qsprintf(
|
||||
$conn_r,
|
||||
' AND authorPHID = %s',
|
||||
$this->viewPHID);
|
||||
}
|
||||
|
||||
$data = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT * FROM %T
|
||||
%Q
|
||||
ORDER BY id DESC
|
||||
LIMIT %d, %d',
|
||||
$rule->getTableName(),
|
||||
$where_clause,
|
||||
$pager->getOffset(),
|
||||
$pager->getPageSize() + 1);
|
||||
$data = $pager->sliceResults($data);
|
||||
$rules = $rule->loadAllFromArray($data);
|
||||
|
||||
$need_phids = mpull($rules, 'getAuthorPHID');
|
||||
if ($this->viewPHID) {
|
||||
$need_phids[] = $this->viewPHID;
|
||||
}
|
||||
|
||||
$handles = id(new PhabricatorObjectHandleData($need_phids))
|
||||
->loadHandles();
|
||||
|
||||
return array($rules, $handles);
|
||||
}
|
||||
}
|
||||
|
27
src/applications/herald/controller/all/__init__.php
Normal file
27
src/applications/herald/controller/all/__init__.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||
phutil_require_module('phabricator', 'applications/herald/config/contenttype');
|
||||
phutil_require_module('phabricator', 'applications/herald/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/herald/storage/rule');
|
||||
phutil_require_module('phabricator', 'applications/herald/view/rulelist');
|
||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||
phutil_require_module('phabricator', 'storage/qsprintf');
|
||||
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/tokenizer');
|
||||
phutil_require_module('phabricator', 'view/layout/listfilter');
|
||||
phutil_require_module('phabricator', 'view/layout/sidenav');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('HeraldAllRulesController.php');
|
|
@ -29,25 +29,35 @@ abstract class HeraldController extends PhabricatorController {
|
|||
|
||||
$doclink = PhabricatorEnv::getDoclink('article/Herald_User_Guide.html');
|
||||
|
||||
$page->setTabs(
|
||||
array(
|
||||
'rules' => array(
|
||||
'href' => '/herald/',
|
||||
'name' => 'Rules',
|
||||
),
|
||||
'test' => array(
|
||||
'href' => '/herald/test/',
|
||||
'name' => 'Test Console',
|
||||
),
|
||||
'transcripts' => array(
|
||||
'href' => '/herald/transcript/',
|
||||
'name' => 'Transcripts',
|
||||
),
|
||||
'help' => array(
|
||||
'href' => $doclink,
|
||||
'name' => 'Help',
|
||||
),
|
||||
$tabs = array(
|
||||
'rules' => array(
|
||||
'href' => '/herald/',
|
||||
'name' => 'Rules',
|
||||
),
|
||||
'test' => array(
|
||||
'href' => '/herald/test/',
|
||||
'name' => 'Test Console',
|
||||
),
|
||||
'transcripts' => array(
|
||||
'href' => '/herald/transcript/',
|
||||
'name' => 'Transcripts',
|
||||
),
|
||||
'help' => array(
|
||||
'href' => $doclink,
|
||||
'name' => 'Help',
|
||||
),
|
||||
);
|
||||
|
||||
$user = $this->getRequest()->getUser();
|
||||
if ($user->getIsAdmin()) {
|
||||
$tabs['all'] = array(
|
||||
'href' => '/herald/all',
|
||||
'name' => 'All Rules',
|
||||
);
|
||||
}
|
||||
|
||||
$page->setTabs(
|
||||
$tabs,
|
||||
idx($data, 'tab'));
|
||||
|
||||
$response = new AphrontWebpageResponse();
|
||||
|
|
|
@ -34,7 +34,7 @@ class HeraldDeleteController extends HeraldController {
|
|||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
if ($user->getPHID() != $rule->getAuthorPHID()) {
|
||||
if ($user->getPHID() != $rule->getAuthorPHID() && !$user->getIsAdmin()) {
|
||||
return new Aphront400Response();
|
||||
}
|
||||
|
||||
|
|
|
@ -44,64 +44,13 @@ class HeraldHomeController extends HeraldController {
|
|||
$handles = id(new PhabricatorObjectHandleData($need_phids))
|
||||
->loadHandles();
|
||||
|
||||
$type = 'differential';
|
||||
|
||||
$rows = array();
|
||||
foreach ($rules as $rule) {
|
||||
$owner = $handles[$rule->getAuthorPHID()]->renderLink();
|
||||
|
||||
$name = phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/herald/rule/'.$rule->getID().'/',
|
||||
),
|
||||
phutil_escape_html($rule->getName()));
|
||||
|
||||
$delete = 'delete';
|
||||
$delete = javelin_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/herald/delete/'.$rule->getID().'/',
|
||||
'sigil' => 'workflow',
|
||||
'class' => 'button small grey',
|
||||
),
|
||||
'Delete');
|
||||
|
||||
$rows[] = array(
|
||||
$map[$rule->getContentType()],
|
||||
$owner,
|
||||
$name,
|
||||
$delete,
|
||||
);
|
||||
}
|
||||
|
||||
$rules_for = phutil_escape_html($map[$this->view]);
|
||||
|
||||
$table = new AphrontTableView($rows);
|
||||
$table->setNoDataString(
|
||||
"No matching subscription rules for {$rules_for}.");
|
||||
|
||||
$table->setHeaders(
|
||||
array(
|
||||
'Type',
|
||||
'Owner',
|
||||
'Rule Name',
|
||||
'',
|
||||
));
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
'',
|
||||
'',
|
||||
'wide wrap pri',
|
||||
'action'
|
||||
));
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader("Herald Rules for {$rules_for}");
|
||||
$panel->setCreateButton(
|
||||
'Create New Herald Rule',
|
||||
'/herald/new/'.$this->view.'/');
|
||||
$panel->appendChild($table);
|
||||
$list_view = id(new HeraldRuleListView())
|
||||
->setRules($rules)
|
||||
->setHandles($handles)
|
||||
->setMap($map)
|
||||
->setAllowCreation(true)
|
||||
->setView($this->view);
|
||||
$panel = $list_view->render();
|
||||
|
||||
$sidenav = new AphrontSideNavView();
|
||||
$sidenav->appendChild($panel);
|
||||
|
|
|
@ -9,10 +9,8 @@
|
|||
phutil_require_module('phabricator', 'applications/herald/config/contenttype');
|
||||
phutil_require_module('phabricator', 'applications/herald/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/herald/storage/rule');
|
||||
phutil_require_module('phabricator', 'applications/herald/view/rulelist');
|
||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
phutil_require_module('phabricator', 'view/layout/sidenav');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -36,7 +36,7 @@ class HeraldRuleController extends HeraldController {
|
|||
if (!$rule) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
if ($rule->getAuthorPHID() != $user->getPHID()) {
|
||||
if ($rule->getAuthorPHID() != $user->getPHID() && !$user->getIsAdmin()) {
|
||||
throw new Exception("You don't own this rule and can't edit it.");
|
||||
}
|
||||
} else {
|
||||
|
|
115
src/applications/herald/view/rulelist/HeraldRuleListView.php
Normal file
115
src/applications/herald/view/rulelist/HeraldRuleListView.php
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 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 HeraldRuleListView extends AphrontView {
|
||||
private $rules;
|
||||
private $handles;
|
||||
private $map;
|
||||
private $view;
|
||||
private $allowCreation;
|
||||
|
||||
public function setRules(array $rules) {
|
||||
$this->rules = $rules;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHandles(array $handles) {
|
||||
$this->handles = $handles;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setMap($map) {
|
||||
$this->map = $map;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setView($view) {
|
||||
$this->view = $view;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setAllowCreation($allow_creation) {
|
||||
$this->allowCreation = $allow_creation;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$rows = array();
|
||||
foreach ($this->rules as $rule) {
|
||||
$owner = $this->handles[$rule->getAuthorPHID()]->renderLink();
|
||||
|
||||
$name = phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/herald/rule/'.$rule->getID().'/',
|
||||
),
|
||||
phutil_escape_html($rule->getName()));
|
||||
|
||||
$delete = javelin_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/herald/delete/'.$rule->getID().'/',
|
||||
'sigil' => 'workflow',
|
||||
'class' => 'button small grey',
|
||||
),
|
||||
'Delete');
|
||||
|
||||
$rows[] = array(
|
||||
$this->map[$rule->getContentType()],
|
||||
$owner,
|
||||
$name,
|
||||
$delete,
|
||||
);
|
||||
}
|
||||
|
||||
$rules_for = phutil_escape_html($this->map[$this->view]);
|
||||
|
||||
$table = new AphrontTableView($rows);
|
||||
$table->setNoDataString(
|
||||
"No matching subscription rules for {$rules_for}.");
|
||||
|
||||
$table->setHeaders(
|
||||
array(
|
||||
'Type',
|
||||
'Owner',
|
||||
'Rule Name',
|
||||
'',
|
||||
));
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
'',
|
||||
'',
|
||||
'wide wrap pri',
|
||||
'action'
|
||||
));
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader("Herald Rules for {$rules_for}");
|
||||
|
||||
if ($this->allowCreation) {
|
||||
$panel->setCreateButton(
|
||||
'Create New Herald Rule',
|
||||
'/herald/new/'.$this->view.'/');
|
||||
}
|
||||
|
||||
$panel->appendChild($table);
|
||||
|
||||
return $panel;
|
||||
|
||||
}
|
||||
}
|
17
src/applications/herald/view/rulelist/__init__.php
Normal file
17
src/applications/herald/view/rulelist/__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', 'infrastructure/javelin/markup');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
||||
|
||||
phutil_require_source('HeraldRuleListView.php');
|
Loading…
Reference in a new issue