1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-27 22:19:29 +01:00

Improve repository hinting and feedback

Summary:
  - Warn about "Read/Write" instead of disabling it, to prevent edits which mutate it after changing a hosted repository to an unhosted one.
  - Warn about authenticated connections with HTTPS auth disabled, and link to the relevant setting.
  - When "Autoclose" is disabled, show that "Autoclose Branches" won't have an effect.
  - For hosted repositories, show the HTTP and SSH clone URIs.
    - Make them easy to copy/paste.
    - Link to credential management.
    - Show if they're read-only.
    - This could be a bit nicer-looking than it is.

Test Plan: Looked at repositories in a bunch of states and made various edits to them.

Reviewers: btrahan, chad

Reviewed By: btrahan

CC: chad, aran

Maniphest Tasks: T2230

Differential Revision: https://secure.phabricator.com/D7471
This commit is contained in:
epriestley 2013-11-01 17:35:43 -07:00
parent d1649d176f
commit a0e820ad9a
8 changed files with 232 additions and 40 deletions

View file

@ -1145,7 +1145,7 @@ celerity_register_resource_map(array(
), ),
'diffusion-icons-css' => 'diffusion-icons-css' =>
array( array(
'uri' => '/res/b93e32c9/rsrc/css/application/diffusion/diffusion-icons.css', 'uri' => '/res/82e77537/rsrc/css/application/diffusion/diffusion-icons.css',
'type' => 'css', 'type' => 'css',
'requires' => 'requires' =>
array( array(
@ -2485,6 +2485,18 @@ celerity_register_resource_map(array(
), ),
'disk' => '/rsrc/js/application/search/behavior-reorder-queries.js', 'disk' => '/rsrc/js/application/search/behavior-reorder-queries.js',
), ),
'javelin-behavior-select-on-click' =>
array(
'uri' => '/res/f021b754/rsrc/js/core/behavior-select-on-click.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/core/behavior-select-on-click.js',
),
'javelin-behavior-slowvote-embed' => 'javelin-behavior-slowvote-embed' =>
array( array(
'uri' => '/res/8e85e20d/rsrc/js/application/slowvote/behavior-slowvote-embed.js', 'uri' => '/res/8e85e20d/rsrc/js/application/slowvote/behavior-slowvote-embed.js',
@ -4470,7 +4482,7 @@ celerity_register_resource_map(array(
'uri' => '/res/pkg/5e9e5c4e/differential.pkg.js', 'uri' => '/res/pkg/5e9e5c4e/differential.pkg.js',
'type' => 'js', 'type' => 'js',
), ),
'270f4eb4' => '7aa115b4' =>
array( array(
'name' => 'diffusion.pkg.css', 'name' => 'diffusion.pkg.css',
'symbols' => 'symbols' =>
@ -4478,7 +4490,7 @@ celerity_register_resource_map(array(
0 => 'diffusion-commit-view-css', 0 => 'diffusion-commit-view-css',
1 => 'diffusion-icons-css', 1 => 'diffusion-icons-css',
), ),
'uri' => '/res/pkg/270f4eb4/diffusion.pkg.css', 'uri' => '/res/pkg/7aa115b4/diffusion.pkg.css',
'type' => 'css', 'type' => 'css',
), ),
96909266 => 96909266 =>
@ -4570,8 +4582,8 @@ celerity_register_resource_map(array(
'differential-revision-history-css' => '1084b12b', 'differential-revision-history-css' => '1084b12b',
'differential-revision-list-css' => '1084b12b', 'differential-revision-list-css' => '1084b12b',
'differential-table-of-contents-css' => '1084b12b', 'differential-table-of-contents-css' => '1084b12b',
'diffusion-commit-view-css' => '270f4eb4', 'diffusion-commit-view-css' => '7aa115b4',
'diffusion-icons-css' => '270f4eb4', 'diffusion-icons-css' => '7aa115b4',
'global-drag-and-drop-css' => 'b05e33c6', 'global-drag-and-drop-css' => 'b05e33c6',
'inline-comment-summary-css' => '1084b12b', 'inline-comment-summary-css' => '1084b12b',
'javelin-aphlict' => '2c1dba03', 'javelin-aphlict' => '2c1dba03',

View file

@ -101,7 +101,14 @@ final class PhabricatorDiffusionConfigOptions
"long as Phabricator uses HTTPS, but it presents a much lower ". "long as Phabricator uses HTTPS, but it presents a much lower ".
"barrier to attackers than SSH does.\n\n". "barrier to attackers than SSH does.\n\n".
"Consider using SSH for authenticated access to repositories ". "Consider using SSH for authenticated access to repositories ".
"instead of HTTP.")) "instead of HTTP.")),
$this->newOption('diffusion.ssh-user', 'string', null)
->setSummary(pht('Login username for SSH connections to repositories.'))
->setDescription(
pht(
'When constructing clone URIs to show to users, Diffusion will '.
'fill in this login username. If you have configured a VCS user '.
'like `git`, you should provide it here.')),
); );
} }

View file

@ -165,18 +165,64 @@ final class DiffusionRepositoryController extends DiffusionController {
->setUser($user); ->setUser($user);
$view->addProperty(pht('Callsign'), $repository->getCallsign()); $view->addProperty(pht('Callsign'), $repository->getCallsign());
switch ($repository->getVersionControlSystem()) { if ($repository->isHosted()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $serve_off = PhabricatorRepository::SERVE_OFF;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $callsign = $repository->getCallsign();
$view->addProperty( $repo_path = '/diffusion/'.$callsign.'/';
pht('Clone URI'),
$repository->getPublicRemoteURI()); $serve_ssh = $repository->getServeOverSSH();
break; if ($serve_ssh !== $serve_off) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $uri = new PhutilURI(PhabricatorEnv::getProductionURI($repo_path));
$view->addProperty( $uri->setProtocol('ssh');
pht('Repository Root'),
$repository->getPublicRemoteURI()); $ssh_user = PhabricatorEnv::getEnvConfig('diffusion.ssh-user');
break; if ($ssh_user) {
$uri->setUser($ssh_user);
}
// This isn't quite right, but for now it's probably better to drop
// the port than sometimes show ":8080", etc. Using most VCS commands
// against nonstandard ports is a huge pain so few installs are likely
// to configure SSH on a nonstandard port.
$uri->setPort(null);
$clone_uri = $this->renderCloneURI(
$uri,
$serve_ssh,
'/settings/panel/ssh/');
$view->addProperty(pht('Clone URI (SSH)'), $clone_uri);
}
$serve_http = $repository->getServeOverHTTP();
if ($serve_http !== $serve_off) {
$http_uri = PhabricatorEnv::getProductionURI($repo_path);
$clone_uri = $this->renderCloneURI(
$http_uri,
$serve_http,
PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth')
? '/settings/panel/vcspassword/'
: null);
$view->addProperty(pht('Clone URI (HTTP)'), $clone_uri);
}
} else {
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$view->addProperty(
pht('Clone URI'),
$this->renderCloneURI(
$repository->getPublicRemoteURI()));
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$view->addProperty(
pht('Repository Root'),
$this->renderCloneURI(
$repository->getPublicRemoteURI()));
break;
}
} }
$description = $repository->getDetail('description'); $description = $repository->getDetail('description');
@ -456,4 +502,53 @@ final class DiffusionRepositoryController extends DiffusionController {
return $browse_panel; return $browse_panel;
} }
private function renderCloneURI(
$uri,
$serve_mode = null,
$manage_uri = null) {
require_celerity_resource('diffusion-icons-css');
Javelin::initBehavior('select-on-click');
$input = javelin_tag(
'input',
array(
'type' => 'text',
'value' => (string)$uri,
'class' => 'diffusion-clone-uri',
'sigil' => 'select-on-click',
));
$extras = array();
if ($serve_mode) {
if ($serve_mode === PhabricatorRepository::SERVE_READONLY) {
$extras[] = pht('(Read Only)');
}
}
if ($manage_uri) {
if ($this->getRequest()->getUser()->isLoggedIn()) {
$extras[] = phutil_tag(
'a',
array(
'href' => $manage_uri,
),
pht('Manage Credentials'));
}
}
if ($extras) {
$extras = phutil_implode_html(' ', $extras);
$extras = phutil_tag(
'div',
array(
'class' => 'diffusion-clone-extras',
),
$extras);
}
return array($input, $extras);
}
} }

View file

@ -126,8 +126,12 @@ final class DiffusionRepositoryEditHostingController
$request = $this->getRequest(); $request = $this->getRequest();
$user = $request->getUser(); $user = $request->getUser();
$v_http_mode = $repository->getServeOverHTTP(); $v_http_mode = $repository->getDetail(
$v_ssh_mode = $repository->getServeOverSSH(); 'serve-over-http',
PhabricatorRepository::SERVE_OFF);
$v_ssh_mode = $repository->getDetail(
'serve-over-ssh',
PhabricatorRepository::SERVE_OFF);
$edit_uri = $this->getRepositoryControllerURI($repository, 'edit/'); $edit_uri = $this->getRepositoryControllerURI($repository, 'edit/');
$prev_uri = $this->getRepositoryControllerURI($repository, 'edit/hosting/'); $prev_uri = $this->getRepositoryControllerURI($repository, 'edit/hosting/');
@ -167,13 +171,19 @@ final class DiffusionRepositoryEditHostingController
$title = pht('Edit Protocols (%s)', $repository->getName()); $title = pht('Edit Protocols (%s)', $repository->getName());
if ($repository->isHosted()) { $rw_message = pht(
$rw_message = pht( 'Phabricator will serve a read-write copy of this repository.');
'Phabricator will serve a read-write copy of this repository');
} else { if (!$repository->isHosted()) {
$rw_message = pht( $rw_message = array(
'This repository is hosted elsewhere, so Phabricator can not perform '. $rw_message,
'writes.'); phutil_tag('br'),
phutil_tag('br'),
pht(
'%s: This repository is hosted elsewhere, so Phabricator can not '.
'perform writes. This mode will act like "Read Only" for '.
'repositories hosted elsewhere.',
phutil_tag('strong', array(), 'WARNING')));
} }
$ssh_control = $ssh_control =
@ -185,19 +195,19 @@ final class DiffusionRepositoryEditHostingController
PhabricatorRepository::SERVE_OFF, PhabricatorRepository::SERVE_OFF,
PhabricatorRepository::getProtocolAvailabilityName( PhabricatorRepository::getProtocolAvailabilityName(
PhabricatorRepository::SERVE_OFF), PhabricatorRepository::SERVE_OFF),
pht('Phabricator will not serve this repository.')) pht('Phabricator will not serve this repository over SSH.'))
->addButton( ->addButton(
PhabricatorRepository::SERVE_READONLY, PhabricatorRepository::SERVE_READONLY,
PhabricatorRepository::getProtocolAvailabilityName( PhabricatorRepository::getProtocolAvailabilityName(
PhabricatorRepository::SERVE_READONLY), PhabricatorRepository::SERVE_READONLY),
pht('Phabricator will serve a read-only copy of this repository.')) pht(
'Phabricator will serve a read-only copy of this repository '.
'over SSH.'))
->addButton( ->addButton(
PhabricatorRepository::SERVE_READWRITE, PhabricatorRepository::SERVE_READWRITE,
PhabricatorRepository::getProtocolAvailabilityName( PhabricatorRepository::getProtocolAvailabilityName(
PhabricatorRepository::SERVE_READWRITE), PhabricatorRepository::SERVE_READWRITE),
$rw_message, $rw_message);
$repository->isHosted() ? null : 'disabled',
$repository->isHosted() ? null : true);
$http_control = $http_control =
id(new AphrontFormRadioButtonControl()) id(new AphrontFormRadioButtonControl())
@ -208,19 +218,19 @@ final class DiffusionRepositoryEditHostingController
PhabricatorRepository::SERVE_OFF, PhabricatorRepository::SERVE_OFF,
PhabricatorRepository::getProtocolAvailabilityName( PhabricatorRepository::getProtocolAvailabilityName(
PhabricatorRepository::SERVE_OFF), PhabricatorRepository::SERVE_OFF),
pht('Phabricator will not serve this repository.')) pht('Phabricator will not serve this repository over HTTP.'))
->addButton( ->addButton(
PhabricatorRepository::SERVE_READONLY, PhabricatorRepository::SERVE_READONLY,
PhabricatorRepository::getProtocolAvailabilityName( PhabricatorRepository::getProtocolAvailabilityName(
PhabricatorRepository::SERVE_READONLY), PhabricatorRepository::SERVE_READONLY),
pht('Phabricator will serve a read-only copy of this repository.')) pht(
'Phabricator will serve a read-only copy of this repository '.
'over HTTP.'))
->addButton( ->addButton(
PhabricatorRepository::SERVE_READWRITE, PhabricatorRepository::SERVE_READWRITE,
PhabricatorRepository::getProtocolAvailabilityName( PhabricatorRepository::getProtocolAvailabilityName(
PhabricatorRepository::SERVE_READWRITE), PhabricatorRepository::SERVE_READWRITE),
$rw_message, $rw_message);
$repository->isHosted() ? null : 'disabled',
$repository->isHosted() ? null : true);
$form = id(new AphrontFormView()) $form = id(new AphrontFormView())
->setUser($user) ->setUser($user)
@ -228,7 +238,19 @@ final class DiffusionRepositoryEditHostingController
pht( pht(
'Phabricator can serve repositories over various protocols. You can '. 'Phabricator can serve repositories over various protocols. You can '.
'configure server protocols here.')) 'configure server protocols here.'))
->appendChild($ssh_control) ->appendChild($ssh_control);
if (!PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth')) {
$form->appendRemarkupInstructions(
pht(
'NOTE: The configuration setting [[ %s | %s ]] is currently '.
'disabled. You must enable it to activate authenticated access '.
'to repositories over HTTP.',
'/config/edit/diffusion.allow-http-auth/',
'diffusion.allow-http-auth'));
}
$form
->appendChild($http_control) ->appendChild($http_control)
->appendChild( ->appendChild(
id(new AphrontFormSubmitControl()) id(new AphrontFormSubmitControl())

View file

@ -349,6 +349,11 @@ final class DiffusionRepositoryEditMainController
$autoclose_only = nonempty( $autoclose_only = nonempty(
$repository->getHumanReadableDetail('close-commits-filter', array()), $repository->getHumanReadableDetail('close-commits-filter', array()),
phutil_tag('em', array(), pht('Autoclose On All Branches'))); phutil_tag('em', array(), pht('Autoclose On All Branches')));
if ($repository->getDetail('disable-autoclose')) {
$autoclose_only = phutil_tag('em', array(), pht('Disabled'));
}
$view->addProperty(pht('Autoclose Only'), $autoclose_only); $view->addProperty(pht('Autoclose Only'), $autoclose_only);
return $view; return $view;

View file

@ -737,7 +737,8 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
} }
public function getServeOverHTTP() { public function getServeOverHTTP() {
return $this->getDetail('serve-over-http', self::SERVE_OFF); $serve = $this->getDetail('serve-over-http', self::SERVE_OFF);
return $this->normalizeServeConfigSetting($serve);
} }
public function setServeOverHTTP($mode) { public function setServeOverHTTP($mode) {
@ -745,7 +746,8 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
} }
public function getServeOverSSH() { public function getServeOverSSH() {
return $this->getDetail('serve-over-ssh', self::SERVE_OFF); $serve = $this->getDetail('serve-over-ssh', self::SERVE_OFF);
return $this->normalizeServeConfigSetting($serve);
} }
public function setServeOverSSH($mode) { public function setServeOverSSH($mode) {
@ -765,6 +767,22 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
} }
} }
private function normalizeServeConfigSetting($value) {
switch ($value) {
case self::SERVE_OFF:
case self::SERVE_READONLY:
return $value;
case self::SERVE_READWRITE:
if ($this->isHosted()) {
return self::SERVE_READWRITE;
} else {
return self::SERVE_READONLY;
}
default:
return self::SERVE_OFF;
}
}
/** /**
* Raise more useful errors when there are basic filesystem problems. * Raise more useful errors when there are basic filesystem problems.

View file

@ -26,3 +26,17 @@
.diffusion-path-icon-link { .diffusion-path-icon-link {
background-image: url(/rsrc/image/icon/fatcow/page_white_link.png); background-image: url(/rsrc/image/icon/fatcow/page_white_link.png);
} }
input.diffusion-clone-uri {
display: block;
width: 100%;
border: 1px solid #efefef;
box-shadow: none;
height: 24px;
}
.diffusion-clone-extras {
font-size: 11px;
text-align: right;
color: {$lightgreytext};
}

View file

@ -0,0 +1,19 @@
/**
* @provides javelin-behavior-select-on-click
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
* @javelin
*/
JX.behavior('select-on-click', function(config) {
JX.Stratcom.listen(
'click',
'select-on-click',
function(e) {
e.kill();
var node = e.getNode('select-on-click');
JX.DOM.focus(node);
node.select();
});
});