mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-27 01:02:42 +01:00
Add owners.query method
Summary: Allow callers to find all packages/paths owned by a given user/project. Test Plan: Used conduit api page with -- user owner: PHID-USER-6ce1c976b86e5f3c34f6 (tried both loadPackagesFromProjects true/false) proj owner: PHID-PROJ-r5wnmmaawqsn4tvjmqm4 repo/path: E, /tfb/trunk/www/flib/privacy. Checked both path.getowners and owners.query (all of these are defined internally at fb) Reviewers: epriestley, btrahan, nh Reviewed By: btrahan CC: aran, Koolvin Differential Revision: https://secure.phabricator.com/D2482
This commit is contained in:
parent
a009c93350
commit
787c95abd8
5 changed files with 213 additions and 12 deletions
|
@ -165,6 +165,7 @@ phutil_register_library_map(array(
|
||||||
'ConduitAPI_maniphest_gettasktransactions_Method' => 'applications/conduit/method/maniphest/gettasktransactions',
|
'ConduitAPI_maniphest_gettasktransactions_Method' => 'applications/conduit/method/maniphest/gettasktransactions',
|
||||||
'ConduitAPI_maniphest_info_Method' => 'applications/conduit/method/maniphest/info',
|
'ConduitAPI_maniphest_info_Method' => 'applications/conduit/method/maniphest/info',
|
||||||
'ConduitAPI_maniphest_update_Method' => 'applications/conduit/method/maniphest/update',
|
'ConduitAPI_maniphest_update_Method' => 'applications/conduit/method/maniphest/update',
|
||||||
|
'ConduitAPI_owners_query_Method' => 'applications/conduit/method/owners/query',
|
||||||
'ConduitAPI_paste_Method' => 'applications/conduit/method/paste/base',
|
'ConduitAPI_paste_Method' => 'applications/conduit/method/paste/base',
|
||||||
'ConduitAPI_paste_create_Method' => 'applications/conduit/method/paste/create',
|
'ConduitAPI_paste_create_Method' => 'applications/conduit/method/paste/create',
|
||||||
'ConduitAPI_paste_info_Method' => 'applications/conduit/method/paste/info',
|
'ConduitAPI_paste_info_Method' => 'applications/conduit/method/paste/info',
|
||||||
|
@ -1201,6 +1202,7 @@ phutil_register_library_map(array(
|
||||||
'ConduitAPI_maniphest_gettasktransactions_Method' => 'ConduitAPI_maniphest_Method',
|
'ConduitAPI_maniphest_gettasktransactions_Method' => 'ConduitAPI_maniphest_Method',
|
||||||
'ConduitAPI_maniphest_info_Method' => 'ConduitAPI_maniphest_Method',
|
'ConduitAPI_maniphest_info_Method' => 'ConduitAPI_maniphest_Method',
|
||||||
'ConduitAPI_maniphest_update_Method' => 'ConduitAPI_maniphest_Method',
|
'ConduitAPI_maniphest_update_Method' => 'ConduitAPI_maniphest_Method',
|
||||||
|
'ConduitAPI_owners_query_Method' => 'ConduitAPIMethod',
|
||||||
'ConduitAPI_paste_Method' => 'ConduitAPIMethod',
|
'ConduitAPI_paste_Method' => 'ConduitAPIMethod',
|
||||||
'ConduitAPI_paste_create_Method' => 'ConduitAPI_paste_Method',
|
'ConduitAPI_paste_create_Method' => 'ConduitAPI_paste_Method',
|
||||||
'ConduitAPI_paste_info_Method' => 'ConduitAPI_paste_Method',
|
'ConduitAPI_paste_info_Method' => 'ConduitAPI_paste_Method',
|
||||||
|
|
|
@ -0,0 +1,177 @@
|
||||||
|
<?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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group conduit
|
||||||
|
*/
|
||||||
|
final class ConduitAPI_owners_query_Method
|
||||||
|
extends ConduitAPIMethod {
|
||||||
|
|
||||||
|
public function getMethodDescription() {
|
||||||
|
return 'Query for packages by one of the following: repository/path, ' .
|
||||||
|
'packages with a given user or project owner, or packages affiliated ' .
|
||||||
|
'with a user (owned by either the user or a project they are a member ' .
|
||||||
|
'of.) You should only provide at most one search query.';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defineParamTypes() {
|
||||||
|
return array(
|
||||||
|
'userOwner' => 'optional string',
|
||||||
|
'projectOwner' => 'optional string',
|
||||||
|
'userAffiliated' => 'optional string',
|
||||||
|
'repositoryCallsign' => 'optional string',
|
||||||
|
'path' => 'optional string',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defineReturnType() {
|
||||||
|
return 'dict<phid -> dict of package info>';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defineErrorTypes() {
|
||||||
|
return array(
|
||||||
|
'ERR-INVALID-USAGE' =>
|
||||||
|
'Provide one of a single owner phid (user/project), a single ' .
|
||||||
|
'affiliated user phid (user), or a repository/path.',
|
||||||
|
'ERR-INVALID-PARAMETER' => 'parameter should be a phid',
|
||||||
|
'ERR_REP_NOT_FOUND' => 'The repository callsign is not recognized',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function queryByOwner($owner) {
|
||||||
|
$is_valid_phid =
|
||||||
|
phid_get_type($owner) == PhabricatorPHIDConstants::PHID_TYPE_USER ||
|
||||||
|
phid_get_type($owner) == PhabricatorPHIDConstants::PHID_TYPE_PROJ;
|
||||||
|
|
||||||
|
if (!$is_valid_phid) {
|
||||||
|
throw id(new ConduitException('ERR-INVALID-PARAMETER'))
|
||||||
|
->setErrorDescription(
|
||||||
|
'Expected user/project PHID for owner, got '.$owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
$owners = id(new PhabricatorOwnersOwner())->loadAllWhere(
|
||||||
|
'userPHID = %s',
|
||||||
|
$owner);
|
||||||
|
|
||||||
|
$package_ids = mpull($owners, 'getPackageID');
|
||||||
|
$packages = array();
|
||||||
|
foreach ($package_ids as $id) {
|
||||||
|
$packages[] = id(new PhabricatorOwnersPackage())->load($id);
|
||||||
|
}
|
||||||
|
return $packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function queryByAffiliatedUser($owner) {
|
||||||
|
$is_valid_phid =
|
||||||
|
phid_get_type($owner) == PhabricatorPHIDConstants::PHID_TYPE_USER;
|
||||||
|
|
||||||
|
if (!$is_valid_phid) {
|
||||||
|
throw id(new ConduitException('ERR-INVALID-PARAMETER'))
|
||||||
|
->setErrorDescription(
|
||||||
|
'Expected user PHID for affiliation, got '.$owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
$owners = PhabricatorOwnersOwner::loadAffiliatedPackages($owner);
|
||||||
|
|
||||||
|
$package_ids = mpull($owners, 'getPackageID');
|
||||||
|
$packages = array();
|
||||||
|
foreach ($package_ids as $id) {
|
||||||
|
$packages[] = id(new PhabricatorOwnersPackage())->load($id);
|
||||||
|
}
|
||||||
|
return $packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function queryByPath($repo_callsign, $path) {
|
||||||
|
// note: we call this from the deprecated path.getowners conduit call.
|
||||||
|
|
||||||
|
$repository = id(new PhabricatorRepository())->loadOneWhere('callsign = %s',
|
||||||
|
$repo_callsign);
|
||||||
|
|
||||||
|
if (empty($repository)) {
|
||||||
|
throw id(new ConduitException('ERR_REP_NOT_FOUND'))
|
||||||
|
->setErrorDescription(
|
||||||
|
'Repository callsign '.$repo_callsign.' not recognized');
|
||||||
|
}
|
||||||
|
|
||||||
|
return PhabricatorOwnersPackage::loadOwningPackages(
|
||||||
|
$repository, $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function buildPackageInformationDictionaries($packages) {
|
||||||
|
assert_instances_of($packages, 'PhabricatorOwnersPackage');
|
||||||
|
|
||||||
|
$result = array();
|
||||||
|
foreach ($packages as $package) {
|
||||||
|
$p_owners = $package->loadOwners();
|
||||||
|
$p_paths = $package->loadPaths();
|
||||||
|
|
||||||
|
$owners = array_values(mpull($p_owners, 'getUserPHID'));
|
||||||
|
$paths = array();
|
||||||
|
foreach ($p_paths as $p) {
|
||||||
|
$paths[] = array($p->getRepositoryPHID(), $p->getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
$result[$package->getPHID()] = array(
|
||||||
|
'phid' => $package->getPHID(),
|
||||||
|
'name' => $package->getName(),
|
||||||
|
'description' => $package->getDescription(),
|
||||||
|
'primaryOwner' => $package->getPrimaryOwnerPHID(),
|
||||||
|
'owners' => $owners,
|
||||||
|
'paths' => $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(ConduitAPIRequest $request) {
|
||||||
|
$is_owner_query =
|
||||||
|
($request->getValue('userOwner') ||
|
||||||
|
$request->getValue('projectOwner')) ?
|
||||||
|
1 : 0;
|
||||||
|
|
||||||
|
$is_affiliated_query = $request->getValue('userAffiliated') ?
|
||||||
|
1 : 0;
|
||||||
|
|
||||||
|
$repo = $request->getValue('repositoryCallsign');
|
||||||
|
$path = $request->getValue('path');
|
||||||
|
$is_path_query = ($repo && $path) ? 1 : 0;
|
||||||
|
|
||||||
|
// exactly one of these should be provided
|
||||||
|
if ($is_owner_query + $is_path_query + $is_affiliated_query !== 1) {
|
||||||
|
throw new ConduitException('ERR-INVALID-USAGE');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($is_affiliated_query) {
|
||||||
|
$packages = self::queryByAffiliatedUser(
|
||||||
|
$request->getValue('userAffiliated'));
|
||||||
|
|
||||||
|
} else if ($is_owner_query) {
|
||||||
|
$owner = nonempty(
|
||||||
|
$request->getValue('userOwner'),
|
||||||
|
$request->getValue('projectOwner'));
|
||||||
|
|
||||||
|
$packages = self::queryByOwner($owner);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$packages = self::queryByPath($repo, $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::buildPackageInformationDictionaries($packages);
|
||||||
|
}
|
||||||
|
}
|
20
src/applications/conduit/method/owners/query/__init__.php
Normal file
20
src/applications/conduit/method/owners/query/__init__.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/method/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/protocol/exception');
|
||||||
|
phutil_require_module('phabricator', 'applications/owners/storage/owner');
|
||||||
|
phutil_require_module('phabricator', 'applications/owners/storage/package');
|
||||||
|
phutil_require_module('phabricator', 'applications/phid/constants');
|
||||||
|
phutil_require_module('phabricator', 'applications/phid/utils');
|
||||||
|
phutil_require_module('phabricator', 'applications/repository/storage/repository');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('ConduitAPI_owners_query_Method.php');
|
|
@ -21,6 +21,15 @@
|
||||||
*/
|
*/
|
||||||
final class ConduitAPI_path_getowners_Method extends ConduitAPIMethod {
|
final class ConduitAPI_path_getowners_Method extends ConduitAPIMethod {
|
||||||
|
|
||||||
|
// This conduit call is deprecated
|
||||||
|
public function getMethodStatus() {
|
||||||
|
return self::METHOD_STATUS_DEPRECATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMethodStatusDescription() {
|
||||||
|
return "Replaced by 'owners.query'.";
|
||||||
|
}
|
||||||
|
|
||||||
public function getMethodDescription() {
|
public function getMethodDescription() {
|
||||||
return "Find the Owners package that contains a given path.";
|
return "Find the Owners package that contains a given path.";
|
||||||
}
|
}
|
||||||
|
@ -50,16 +59,11 @@ final class ConduitAPI_path_getowners_Method extends ConduitAPIMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function execute(ConduitAPIRequest $request) {
|
protected function execute(ConduitAPIRequest $request) {
|
||||||
|
$packages = ConduitAPI_owners_query_Method::queryByPath(
|
||||||
|
$request->getValue('repositoryCallsign'),
|
||||||
|
$request->getValue('path')
|
||||||
|
);
|
||||||
|
|
||||||
$repository = id(new PhabricatorRepository())->loadOneWhere('callsign = %s',
|
|
||||||
$request->getValue('repositoryCallsign'));
|
|
||||||
|
|
||||||
if (empty($repository)) {
|
|
||||||
throw new ConduitException('ERR_REP_NOT_FOUND');
|
|
||||||
}
|
|
||||||
|
|
||||||
$packages = PhabricatorOwnersPackage::loadOwningPackages(
|
|
||||||
$repository, $request->getValue('path'));
|
|
||||||
if (empty($packages)) {
|
if (empty($packages)) {
|
||||||
throw new ConduitException('ERR_PATH_NOT_FOUND');
|
throw new ConduitException('ERR_PATH_NOT_FOUND');
|
||||||
}
|
}
|
||||||
|
@ -79,5 +83,4 @@ final class ConduitAPI_path_getowners_Method extends ConduitAPIMethod {
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,9 @@
|
||||||
|
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'applications/conduit/method/base');
|
phutil_require_module('phabricator', 'applications/conduit/method/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/method/owners/query');
|
||||||
phutil_require_module('phabricator', 'applications/conduit/protocol/exception');
|
phutil_require_module('phabricator', 'applications/conduit/protocol/exception');
|
||||||
phutil_require_module('phabricator', 'applications/owners/storage/owner');
|
phutil_require_module('phabricator', 'applications/owners/storage/owner');
|
||||||
phutil_require_module('phabricator', 'applications/owners/storage/package');
|
|
||||||
phutil_require_module('phabricator', 'applications/repository/storage/repository');
|
|
||||||
|
|
||||||
phutil_require_module('phutil', 'utils');
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue