Implements following rules: - Users - Users of any project - Users of all projects - Administrators - Signers The 'If No Rules Match' the access is implicitly considered to be 'DENY'. It is not possible to control access based on the Moon phase.
293 lines
8.8 KiB
PHP
Executable File
293 lines
8.8 KiB
PHP
Executable File
#!/usr/local/bin/php
|
|
<?php
|
|
|
|
$root = dirname(dirname(dirname(__FILE__)));
|
|
require_once $root.'/scripts/__init_script__.php';
|
|
|
|
function getSVNRepositoryName($repository) {
|
|
$uri = $repository->getRemoteURI();
|
|
return preg_replace(
|
|
'/https?\:\/\/.*?\/svnroot\/([^\/]+)\/?.*/', '$1', $uri);
|
|
}
|
|
|
|
// Get user's heys and put them to the configuration
|
|
function handleSingleUserPHID(
|
|
$viewer, $userPHID, $repository, &$namemap, &$access) {
|
|
$user = id(new PhabricatorPeopleQuery())
|
|
->setViewer($viewer)
|
|
->withPHIDs(array($userPHID))
|
|
->executeOne();
|
|
if (!$user) {
|
|
return;
|
|
}
|
|
|
|
if ($user->getIsDisabled()) {
|
|
return;
|
|
}
|
|
|
|
$user_name = $user->getUserName();
|
|
if (!array_key_exists($user_name, $namemap)) {
|
|
$namemap[$user_name] = array('email' => $user->loadPrimaryEmailAddress(),
|
|
'name' => $user->getRealName());
|
|
}
|
|
|
|
$repository_name = getSVNRepositoryName($repository);
|
|
|
|
$repository_rootpath = $repository_name . ':/';
|
|
if (!array_key_exists($repository_rootpath, $access)) {
|
|
$access[$repository_rootpath]['RW'] = array();
|
|
$access[$repository_rootpath]['RO'] = array();
|
|
}
|
|
$access[$repository_rootpath]['RO'][] = $user_name;
|
|
|
|
// Store write access settings to current subath
|
|
$subpath = $repository->getDetail('svn-subpath');
|
|
$subpath = rtrim($subpath, '/');
|
|
$repository_pathname = "$repository_name:/$subpath";
|
|
if (!array_key_exists($repository_pathname, $access)) {
|
|
$access[$repository_pathname]['RW'] = array();
|
|
$access[$repository_pathname]['RO'] = array();
|
|
}
|
|
$access[$repository_pathname]['RW'][] = $user_name;
|
|
|
|
// Write access to the tags
|
|
$tags_pathname = "$repository_name:/tags";
|
|
if (!array_key_exists($tags_pathname, $access)) {
|
|
$access[$tags_pathname]['RW'] = array();
|
|
$access[$tags_pathname]['RO'] = array();
|
|
}
|
|
$access[$tags_pathname]['RW'][] = $user_name;
|
|
|
|
// Write access to the branches.
|
|
$branches_pathname = "$repository_name:/branches";
|
|
if (!array_key_exists($branches_pathname, $access)) {
|
|
$access[$branches_pathname]['RW'] = array();
|
|
$access[$branches_pathname]['RO'] = array();
|
|
}
|
|
$access[$branches_pathname]['RW'][] = $user_name;
|
|
}
|
|
|
|
function getProjectMembersPHIDs($viewer, $project_phid) {
|
|
$project = id(new PhabricatorProjectQuery())
|
|
->setViewer($viewer)
|
|
->needMembers(true)
|
|
->withPHIDs(array($project_phid))
|
|
->executeOne();
|
|
|
|
return $project->getMemberPHIDs();
|
|
}
|
|
|
|
function handleProjectPHID(
|
|
$viewer, $project_phid, $repository, &$namemap, &$access) {
|
|
$memberPHIDs = getProjectMembersPHIDs($viewer, $project_phid);
|
|
foreach ($memberPHIDs as $memberPHID) {
|
|
handleSingleUserPHID(
|
|
$viewer, $memberPHID, $repository, $namemap, $access);
|
|
}
|
|
}
|
|
|
|
function handleUsersPolicyRule(
|
|
$viewer, $rule, $repository, &$namemap, &$access) {
|
|
foreach ($rule['value'] as $user_phid) {
|
|
handleSingleUserPHID(
|
|
$viewer, $user_phid, $repository, $namemap, $access);
|
|
}
|
|
}
|
|
|
|
function handleProjectsPolicyRule(
|
|
$viewer, $rule, $repository, &$namemap, &$access) {
|
|
foreach ($rule['value'] as $project_phid) {
|
|
handleProjectPHID(
|
|
$viewer, $project_phid, $repository, $namemap, $access);
|
|
}
|
|
}
|
|
|
|
function handleProjectsAllPolicyRule(
|
|
$viewer, $rule, $repository, &$namemap, &$access) {
|
|
$is_first_project = true;
|
|
$allowed_members_phids = array();
|
|
foreach ($rule['value'] as $project_phid) {
|
|
$memberPHIDs = getProjectMembersPHIDs($viewer, $project_phid);
|
|
if ($is_first_project) {
|
|
$allowed_members_phids = $memberPHIDs;
|
|
$is_first_project = false;
|
|
} else {
|
|
$allowed_members_phids = array_intersect(
|
|
$allowed_members_phids, $memberPHIDs);
|
|
}
|
|
}
|
|
|
|
foreach ($allowed_members_phids as $user_phid) {
|
|
handleSingleUserPHID(
|
|
$viewer, $user_phid, $repository, $namemap, $access);
|
|
}
|
|
}
|
|
|
|
function handleAdministratorsPolicyRule(
|
|
$viewer, $rule, $repository, &$namemap, &$access) {
|
|
$administrators = id(new PhabricatorPeopleQuery())
|
|
->setViewer($viewer)
|
|
->withIsAdmin(true)
|
|
->execute();
|
|
foreach ($administrators as $administrator) {
|
|
handleSingleUserPHID(
|
|
$viewer, $administrator->getPHID(), $repository, $namemap, $access);
|
|
}
|
|
}
|
|
|
|
function handleLegalpadSingleDocument(
|
|
$viewer, $document, $repository, &$namemap, &$access) {
|
|
if ($document->getSignatureType() !=
|
|
LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) {
|
|
return;
|
|
}
|
|
|
|
foreach ($document->getSignatures() as $signature) {
|
|
if ($signature->getSignatureType() !=
|
|
LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) {
|
|
continue;
|
|
}
|
|
handleSingleUserPHID(
|
|
$viewer, $signature->getSignerPHID(), $repository, $namemap, $access);
|
|
}
|
|
}
|
|
|
|
function handleLegalpadSignaturePolicyRule(
|
|
$viewer, $rule, $repository, &$namemap, &$access) {
|
|
$documents = id(new LegalpadDocumentQuery())
|
|
->setViewer($viewer)
|
|
->withPHIDs($rule['value'])
|
|
->needSignatures(true)
|
|
->execute();
|
|
|
|
foreach ($documents as $document) {
|
|
handleLegalpadSingleDocument(
|
|
$viewer, $document, $repository, $namemap, $access);
|
|
}
|
|
}
|
|
|
|
function handleCustomPolicyRule(
|
|
$viewer, $rule, $repository, &$namemap, &$access) {
|
|
if ($rule['action'] != PhabricatorPolicy::ACTION_ALLOW) {
|
|
// By default the script decides to DENY unless explicitly allowed.
|
|
return;
|
|
}
|
|
|
|
$rule_type = $rule['rule'];
|
|
if ($rule_type == 'PhabricatorUsersPolicyRule') {
|
|
handleUsersPolicyRule(
|
|
$viewer, $rule, $repository, $namemap, $access);
|
|
} else if ($rule_type == 'PhabricatorProjectsPolicyRule') {
|
|
handleProjectsPolicyRule(
|
|
$viewer, $rule, $repository, $namemap, $access);
|
|
} else if ($rule_type == 'PhabricatorProjectsAllPolicyRule') {
|
|
handleProjectsAllPolicyRule(
|
|
$viewer, $rule, $repository, $namemap, $access);
|
|
} else if ($rule_type == 'PhabricatorAdministratorsPolicyRule') {
|
|
handleAdministratorsPolicyRule(
|
|
$viewer, $rule, $repository, $namemap, $access);
|
|
} else if ($rule_type == 'PhabricatorLegalpadSignaturePolicyRule') {
|
|
handleLegalpadSignaturePolicyRule(
|
|
$viewer, $rule, $repository, $namemap, $access);
|
|
}
|
|
}
|
|
|
|
function handleCustomPolicy(
|
|
$viewer, $policy, $repository, &$namemap, &$access) {
|
|
foreach ($policy->getRules() as $rule) {
|
|
handleCustomPolicyRule($viewer, $rule, $repository, $namemap, $access);
|
|
}
|
|
}
|
|
|
|
// Parse repository and put it's members to the config file
|
|
function handleSingleRepository(
|
|
$viewer, $repository, &$namemap, &$access) {
|
|
$policies = PhabricatorPolicyQuery::loadPolicies(
|
|
$viewer,
|
|
$repository);
|
|
|
|
$pushable = $policies[DiffusionPushCapability::CAPABILITY];
|
|
$type = phid_get_type($pushable->getPHID());
|
|
|
|
// Make sure repository is always available for read-only access
|
|
$repository_rootpath = getSVNRepositoryName($repository) . ':/';
|
|
if (!array_key_exists($repository_rootpath, $access)) {
|
|
$access[$repository_rootpath]['RW'] = array();
|
|
$access[$repository_rootpath]['RO'] = array();
|
|
}
|
|
|
|
if ($type == PhabricatorProjectProjectPHIDType::TYPECONST) {
|
|
handleProjectPHID(
|
|
$viewer, $pushable->getPHID(), $repository, $namemap, $access);
|
|
} else if ($type == PhabricatorPolicyType::TYPE_USER) {
|
|
handleSingleUserPHID(
|
|
$viewer, $pushable->getPHID(), $repository, $namemap, $access);
|
|
} else if ($type == PhabricatorPolicyPHIDTypePolicy::TYPECONST) {
|
|
handleCustomPolicy(
|
|
$viewer, $pushable, $repository, $namemap, $access);
|
|
/* pass */
|
|
} else {
|
|
/* pass */
|
|
}
|
|
}
|
|
|
|
function rebuildConfiguration($what) {
|
|
$viewer = id(new PhabricatorUser())
|
|
->loadOneWhere('username = %s', 'sergey');
|
|
|
|
$repositories = id(new PhabricatorRepositoryQuery())
|
|
->setViewer($viewer)
|
|
->execute();
|
|
|
|
$namemap = array();
|
|
$access = array();
|
|
|
|
require_once 'archived_repos.php';
|
|
foreach ($ARCHIVED_REPOS as $repository) {
|
|
$repository_pathname = "$repository:/";
|
|
$access[$repository_pathname]['RW'] = array();
|
|
$access[$repository_pathname]['RO'] = array();
|
|
}
|
|
|
|
foreach ($repositories as $repository_id => $repository) {
|
|
$type = $repository->getVersionControlSystem();
|
|
if ($type == PhabricatorRepositoryType::REPOSITORY_TYPE_SVN) {
|
|
handleSingleRepository(
|
|
$viewer, $repository, $namemap, $access);
|
|
}
|
|
}
|
|
|
|
if ($what == 'ACCESS') {
|
|
foreach ($access as $repository => $users) {
|
|
print("[$repository]\n");
|
|
$rw_users = array();
|
|
foreach ($users['RW'] as $user) {
|
|
print("$user = rw\n");
|
|
$rw_users[$user] = true;
|
|
}
|
|
foreach ($users['RO'] as $user) {
|
|
if (!array_key_exists($user, $rw_users)) {
|
|
print("$user = r\n");
|
|
}
|
|
}
|
|
print("anonsvn = r\n");
|
|
print("* = r\n\n");
|
|
}
|
|
} else if ($what == 'NAMEMAP') {
|
|
foreach ($namemap as $user => $data) {
|
|
print("$user\t${data['email']}\t${data['name']}\n");
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
if (count($argv) != 2 ||
|
|
($argv[1] != 'ACCESS' && $argv[1] != 'NAMEMAP')) {
|
|
print("Usage: {$argv[0]} ACCESS|NAMEMAP\n");
|
|
exit(1);
|
|
}
|
|
|
|
rebuildConfiguration($argv[1]);
|
|
?>
|