Files
phabricator/scripts/svnauth/rebuild_svnauth.php
Sergey Sharybin 1bcc201b0a Support custom policy for SVN access rules
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.
2020-09-17 12:38:14 +02:00

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]);
?>