1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-27 01:02:42 +01:00

Merge branch 'master' into redesign-2015

This commit is contained in:
epriestley 2015-07-03 13:05:16 -07:00
commit fe4bcde59e
13 changed files with 126 additions and 81 deletions

View file

@ -2661,6 +2661,7 @@ phutil_register_library_map(array(
'PhabricatorSpacesNamespaceSearchEngine' => 'applications/spaces/query/PhabricatorSpacesNamespaceSearchEngine.php', 'PhabricatorSpacesNamespaceSearchEngine' => 'applications/spaces/query/PhabricatorSpacesNamespaceSearchEngine.php',
'PhabricatorSpacesNamespaceTransaction' => 'applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php', 'PhabricatorSpacesNamespaceTransaction' => 'applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php',
'PhabricatorSpacesNamespaceTransactionQuery' => 'applications/spaces/query/PhabricatorSpacesNamespaceTransactionQuery.php', 'PhabricatorSpacesNamespaceTransactionQuery' => 'applications/spaces/query/PhabricatorSpacesNamespaceTransactionQuery.php',
'PhabricatorSpacesNoAccessController' => 'applications/spaces/controller/PhabricatorSpacesNoAccessController.php',
'PhabricatorSpacesRemarkupRule' => 'applications/spaces/remarkup/PhabricatorSpacesRemarkupRule.php', 'PhabricatorSpacesRemarkupRule' => 'applications/spaces/remarkup/PhabricatorSpacesRemarkupRule.php',
'PhabricatorSpacesSchemaSpec' => 'applications/spaces/storage/PhabricatorSpacesSchemaSpec.php', 'PhabricatorSpacesSchemaSpec' => 'applications/spaces/storage/PhabricatorSpacesSchemaSpec.php',
'PhabricatorSpacesTestCase' => 'applications/spaces/__tests__/PhabricatorSpacesTestCase.php', 'PhabricatorSpacesTestCase' => 'applications/spaces/__tests__/PhabricatorSpacesTestCase.php',
@ -4670,6 +4671,7 @@ phutil_register_library_map(array(
'NuanceItem' => array( 'NuanceItem' => array(
'NuanceDAO', 'NuanceDAO',
'PhabricatorPolicyInterface', 'PhabricatorPolicyInterface',
'PhabricatorApplicationTransactionInterface',
), ),
'NuanceItemEditController' => 'NuanceController', 'NuanceItemEditController' => 'NuanceController',
'NuanceItemEditor' => 'PhabricatorApplicationTransactionEditor', 'NuanceItemEditor' => 'PhabricatorApplicationTransactionEditor',
@ -6455,6 +6457,7 @@ phutil_register_library_map(array(
'PhabricatorSpacesNamespaceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorSpacesNamespaceSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorSpacesNamespaceTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorSpacesNamespaceTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorSpacesNamespaceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorSpacesNamespaceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorSpacesNoAccessController' => 'PhabricatorSpacesController',
'PhabricatorSpacesRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorSpacesRemarkupRule' => 'PhabricatorObjectRemarkupRule',
'PhabricatorSpacesSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorSpacesSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PhabricatorSpacesTestCase' => 'PhabricatorTestCase', 'PhabricatorSpacesTestCase' => 'PhabricatorTestCase',

View file

@ -157,19 +157,6 @@ abstract class PhabricatorController extends AphrontController {
} }
} }
$event = new PhabricatorEvent(
PhabricatorEventType::TYPE_CONTROLLER_CHECKREQUEST,
array(
'request' => $request,
'controller' => $this,
));
$event->setUser($user);
PhutilEventEngine::dispatchEvent($event);
$checker_controller = $event->getValue('controller');
if ($checker_controller != $this) {
return $this->delegateToController($checker_controller);
}
$auth_class = 'PhabricatorAuthApplication'; $auth_class = 'PhabricatorAuthApplication';
$auth_application = PhabricatorApplication::getByClass($auth_class); $auth_application = PhabricatorApplication::getByClass($auth_class);
@ -200,7 +187,8 @@ abstract class PhabricatorController extends AphrontController {
if ($this->shouldRequireLogin()) { if ($this->shouldRequireLogin()) {
// This actually means we need either: // This actually means we need either:
// - a valid user, or a public controller; and // - a valid user, or a public controller; and
// - permission to see the application. // - permission to see the application; and
// - permission to see at least one Space if spaces are configured.
$allow_public = $this->shouldAllowPublic() && $allow_public = $this->shouldAllowPublic() &&
PhabricatorEnv::getEnvConfig('policy.allow-public'); PhabricatorEnv::getEnvConfig('policy.allow-public');
@ -223,10 +211,22 @@ abstract class PhabricatorController extends AphrontController {
} }
} }
// If Spaces are configured, require that the user have access to at
// least one. If we don't do this, they'll get confusing error messages
// later on.
$spaces = PhabricatorSpacesNamespaceQuery::getSpacesExist();
if ($spaces) {
$viewer_spaces = PhabricatorSpacesNamespaceQuery::getViewerSpacesExist(
$user);
if (!$viewer_spaces) {
$controller = new PhabricatorSpacesNoAccessController();
return $this->delegateToController($controller);
}
}
// If the user doesn't have access to the application, don't let them use // If the user doesn't have access to the application, don't let them use
// any of its controllers. We query the application in order to generate // any of its controllers. We query the application in order to generate
// a policy exception if the viewer doesn't have permission. // a policy exception if the viewer doesn't have permission.
$application = $this->getCurrentApplication(); $application = $this->getCurrentApplication();
if ($application) { if ($application) {
id(new PhabricatorApplicationQuery()) id(new PhabricatorApplicationQuery())

View file

@ -30,7 +30,7 @@ final class HarbormasterBuildUnitMessage
'namespace' => 'optional string', 'namespace' => 'optional string',
'name' => 'string', 'name' => 'string',
'result' => 'string', 'result' => 'string',
'duration' => 'optional float', 'duration' => 'optional float|int',
'path' => 'optional string', 'path' => 'optional string',
'coverage' => 'optional map<string, wild>', 'coverage' => 'optional map<string, wild>',
); );
@ -44,7 +44,7 @@ final class HarbormasterBuildUnitMessage
$obj->setNamespace(idx($dict, 'namespace', '')); $obj->setNamespace(idx($dict, 'namespace', ''));
$obj->setName($dict['name']); $obj->setName($dict['name']);
$obj->setResult($dict['result']); $obj->setResult($dict['result']);
$obj->setDuration(idx($dict, 'duration')); $obj->setDuration((float)idx($dict, 'duration'));
$path = idx($dict, 'path'); $path = idx($dict, 'path');
if (strlen($path)) { if (strlen($path)) {

View file

@ -49,6 +49,8 @@ final class ManiphestTaskEditBulkJobType
PhabricatorPolicyCapability::CAN_EDIT, PhabricatorPolicyCapability::CAN_EDIT,
)) ))
->withPHIDs(array($task->getObjectPHID())) ->withPHIDs(array($task->getObjectPHID()))
->needProjectPHIDs(true)
->needSubscriberPHIDs(true)
->executeOne(); ->executeOne();
if (!$object) { if (!$object) {
return; return;

View file

@ -16,41 +16,32 @@ final class NuanceRequestorQuery
return $this; return $this;
} }
protected function loadPage() { public function newObject() {
$table = new NuanceRequestor(); return new NuanceRequestor();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
} }
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { protected function loadPage() {
$where = array(); return $this->loadStandardPage($this->newObject());
}
$where[] = $this->buildPagingClause($conn_r); protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids) { if ($this->ids !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'id IN (%Ld)', 'id IN (%Ld)',
$this->ids); $this->ids);
} }
if ($this->phids) { if ($this->phids !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'phid IN (%Ls)', 'phid IN (%Ls)',
$this->phids); $this->phids);
} }
return $this->formatWhereClause($where); return $where;
} }
} }

View file

@ -2,7 +2,9 @@
final class NuanceItem final class NuanceItem
extends NuanceDAO extends NuanceDAO
implements PhabricatorPolicyInterface { implements
PhabricatorPolicyInterface,
PhabricatorApplicationTransactionInterface {
const STATUS_OPEN = 0; const STATUS_OPEN = 0;
const STATUS_ASSIGNED = 10; const STATUS_ASSIGNED = 10;
@ -143,4 +145,27 @@ final class NuanceItem
'dateNuanced' => $this->getDateNuanced(), 'dateNuanced' => $this->getDateNuanced(),
); );
} }
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new NuanceItemEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new NuanceItemTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
} }

View file

@ -31,11 +31,7 @@ final class PhabricatorSpacesApplication extends PhabricatorApplication {
} }
public function canUninstall() { public function canUninstall() {
return true; return false;
}
public function isPrototype() {
return true;
} }
public function getHelpDocumentationArticles(PhabricatorUser $viewer) { public function getHelpDocumentationArticles(PhabricatorUser $viewer) {

View file

@ -0,0 +1,20 @@
<?php
final class PhabricatorSpacesNoAccessController
extends PhabricatorSpacesController {
public function handleRequest(AphrontRequest $request) {
return $this->newDialog()
->setTitle(pht('No Access to Spaces'))
->appendParagraph(
pht(
'This install uses spaces to organize objects, but your account '.
'does not have access to any spaces.'))
->appendParagraph(
pht(
'Ask someone to add you to a Space so you can view and create '.
'objects.'))
->addCancelButton('/', pht('Drift Aimlessly'));
}
}

View file

@ -130,22 +130,6 @@ fields to, e.g., edit revision titles. Data available on this event:
- `specification` Parameters that will be used to invoke the - `specification` Parameters that will be used to invoke the
`differential.createrevision` Conduit call. `differential.createrevision` Conduit call.
== Controller: Check Request ==
The constant for this event is
`PhabricatorEventType::TYPE_CONTROLLER_CHECKREQUEST`.
This event is dispatched when controller is about to begin execution. It is
meant for checking if the user is allowed to use the application at the moment.
It can check if the user has performed too many operations recently, if his IP
address is allowed or if the servers are overloaded to process the request.
Data available on this event:
- `request` Object of class @{class:AphrontRequest}.
- `controller` Class name of the current controller.
You can delegate the execution to another controller by modifying `controller`.
== Maniphest: Will Edit Task == == Maniphest: Will Edit Task ==
The constant for this event is The constant for this event is

View file

@ -92,6 +92,9 @@ You can optionally omit the trailing `=` signs -- that is, these are the same:
This produces headers like the ones in this document. Make sure you have an This produces headers like the ones in this document. Make sure you have an
empty line before and after the header. empty line before and after the header.
Lists
=====
Make **lists** by beginning each item with a `-` or a `*`: Make **lists** by beginning each item with a `-` or a `*`:
lang=text lang=text
@ -117,6 +120,21 @@ You can make numbered lists with a `#` instead of `-` or `*`:
# Zapdos # Zapdos
# Moltres # Moltres
Numbered lists can also be started with `1.` or `1)`. If you use a number other
than `1`, the list will start at that number instead. For example, this:
```
200) OK
201) Created
202) Accepted
```
...produces this:
200) OK
201) Created
202) Accepted
You can also nest lists: You can also nest lists:
```- Body ```- Body

View file

@ -6,20 +6,18 @@ Guide to the Spaces application.
Overview Overview
======== ========
IMPORTANT: Spaces is a prototype application.
The Spaces application makes it easier to manage large groups of objects which The Spaces application makes it easier to manage large groups of objects which
share the same access policy. For example: share the same access policy. For example:
- An organization might make a Space for a project in order to satisfy a - An organization might make a space for a project in order to satisfy a
contractual obligation to limit access, even internally. contractual obligation to limit access, even internally.
- An open source organization might make a Space for work related to - An open source organization might make a space for work related to
internal governance, to separate private and public discussions. internal governance, to separate private and public discussions.
- A contracting company might make Spaces for clients, to separate them from - A contracting company might make spaces for clients, to separate them from
one another. one another.
- A company might create a Space for consultants, to give them limited - A company might create a spaces for consultants, to give them limited
access to only the resources they need to do their work. access to only the resources they need to do their work.
- An ambitious manager might create a Space to hide her team's work from her - An ambitious manager might create a space to hide her team's work from her
enemies at the company, that she might use the element of surprise to later enemies at the company, that she might use the element of surprise to later
expand her domain. expand her domain.
@ -39,16 +37,16 @@ them if you don't plan to use them. You can always set them up later.
To activate Spaces, you need to create at least two spaces. Create spaces from To activate Spaces, you need to create at least two spaces. Create spaces from
the web UI, by navigating to {nav Spaces > Create Space}. By default, only the web UI, by navigating to {nav Spaces > Create Space}. By default, only
administrators can create new Spaces, but you can configure this in the administrators can create new spaces, but you can configure this in the
{nav Applications} application. {nav Applications} application.
The first Space you create will be a special "default" Space, and all existing The first space you create will be a special "default" space, and all existing
objects will be shifted into this space as soon as you create it. Spaces you objects will be shifted into this space as soon as you create it. Spaces you
create later will be normal spaces, and begin with no objects inside them. create later will be normal spaces, and begin with no objects inside them.
Create the first space (you may want to name it something like "Default" or Create the first space (you may want to name it something like "Default" or
"Global" or "Public", depending on the nature of your organization), then "Global" or "Public", depending on the nature of your organization), then
create a second Space. Usually, the second space will be something like create a second space. Usually, the second space will be something like
"Secret Plans" and have a more restrictive "Visible To" policy. "Secret Plans" and have a more restrictive "Visible To" policy.
@ -57,7 +55,7 @@ Using Spaces
Once you've created at least two spaces, you can begin using them. Once you've created at least two spaces, you can begin using them.
Application UIs will change for users who can see at least two Spaces, opening Application UIs will change for users who can see at least two spaces, opening
up new controls which let them work with spaces. They will now be able to up new controls which let them work with spaces. They will now be able to
choose which space to create new objects into, be able to move objects between choose which space to create new objects into, be able to move objects between
spaces, and be able to search for objects in a specific space or set of spaces. spaces, and be able to search for objects in a specific space or set of spaces.
@ -72,14 +70,14 @@ spaces exist. This simplifies the UI for users with limited access.
Space Policies Space Policies
============== ==============
Briefly, Spaces affect policies like this: Briefly, spacess affect policies like this:
- Spaces apply their view policy to all objects inside the space. - Spaces apply their view policy to all objects inside the space.
- Space policies are absolute, and stronger than all other policies. A - Space policies are absolute, and stronger than all other policies. A
user who can not see a Space can **never** see objects inside the space. user who can not see a space can **never** see objects inside the space.
- Normal policies are still checked: spaces can only reduce access. - Normal policies are still checked: spaces can only reduce access.
When you create a Space, you choose a view policy for that space by using the When you create a space, you choose a view policy for that space by using the
**Visible To** control. This policy controls both who can see the space, and **Visible To** control. This policy controls both who can see the space, and
who can see objects inside the space. who can see objects inside the space.
@ -90,21 +88,21 @@ and stronger than all other policy rules, including policy exceptions.
For example, a user can never see a task in a space they can't see, even if For example, a user can never see a task in a space they can't see, even if
they are an admin and the author and owner of the task, and subscribed to the they are an admin and the author and owner of the task, and subscribed to the
task and the view and edit policies are set to "All Users", and they created task and the view and edit policies are set to "All Users", and they created
the Space originally and the moon is full and they are pure of heart and the space originally and the moon is full and they are pure of heart and
possessed of the noblest purpose. Spaces are impenetrable. possessed of the noblest purpose. Spaces are impenetrable.
Even if a user satisfies the view policy for a space, they must still pass the Even if a user satisfies the view policy for a space, they must still pass the
view policy on the object: the space check is a new check in addition to any view policy on the object: the space check is a new check in addition to any
check on the object, and can only limit access. check on the object, and can only limit access.
The edit policy for a space only affects the Space itself, and is not applied The edit policy for a space only affects the space itself, and is not applied
to objects inside the space. to objects inside the space.
Archiving Spaces Archiving Spaces
================ ================
If you no longer need a Space, you can archive it by choosing If you no longer need a space, you can archive it by choosing
{nav Archive Space} from the detail view. This hides the space and all the {nav Archive Space} from the detail view. This hides the space and all the
objects in it without deleting any data. objects in it without deleting any data.
@ -123,14 +121,14 @@ You can reactivate a space later by choosing {nav Activate Space}.
Application Email Application Email
================= =================
After activating Spaces, you can choose a Space when configuring inbound email After activating spaces, you can choose a space when configuring inbound email
addresses in {nav Applications}. addresses in {nav Applications}.
Spaces affect policies for application email just like they do for other Spaces affect policies for application email just like they do for other
objects: to see or use the address, you must be able to see the space which objects: to see or use the address, you must be able to see the space which
contains it. contains it.
Objects created from inbound email will be created in the Space the email is Objects created from inbound email will be created in the space the email is
associated with. associated with.

View file

@ -6,8 +6,6 @@
*/ */
final class PhabricatorEventType extends PhutilEventType { final class PhabricatorEventType extends PhutilEventType {
const TYPE_CONTROLLER_CHECKREQUEST = 'controller.checkRequest';
const TYPE_MANIPHEST_WILLEDITTASK = 'maniphest.willEditTask'; const TYPE_MANIPHEST_WILLEDITTASK = 'maniphest.willEditTask';
const TYPE_MANIPHEST_DIDEDITTASK = 'maniphest.didEditTask'; const TYPE_MANIPHEST_DIDEDITTASK = 'maniphest.didEditTask';

View file

@ -1763,6 +1763,16 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
$viewer = $this->getViewer(); $viewer = $this->getViewer();
// If we have an omnipotent viewer and no formal space constraints, don't
// emit a clause. This primarily enables older migrations to run cleanly,
// without fataling because they try to match a `spacePHID` column which
// does not exist yet. See T8743, T8746.
if ($viewer->isOmnipotent()) {
if ($this->spaceIsArchived === null && $this->spacePHIDs === null) {
return null;
}
}
$space_phids = array(); $space_phids = array();
$include_null = false; $include_null = false;