Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/meta/xactions/PhabricatorApplicationPolicyChangeTransaction.php
12256 views
1
<?php
2
3
final class PhabricatorApplicationPolicyChangeTransaction
4
extends PhabricatorApplicationTransactionType {
5
6
const TRANSACTIONTYPE = 'application.policy';
7
const METADATA_ATTRIBUTE = 'capability.name';
8
9
private $policies;
10
11
public function generateOldValue($object) {
12
$application = $object;
13
$capability = $this->getCapabilityName();
14
return $application->getPolicy($capability);
15
}
16
17
public function applyExternalEffects($object, $value) {
18
$application = $object;
19
$user = $this->getActor();
20
21
$key = 'phabricator.application-settings';
22
$config_entry = PhabricatorConfigEntry::loadConfigEntry($key);
23
$current_value = $config_entry->getValue();
24
25
$phid = $application->getPHID();
26
if (empty($current_value[$phid])) {
27
$current_value[$application->getPHID()] = array();
28
}
29
if (empty($current_value[$phid]['policy'])) {
30
$current_value[$phid]['policy'] = array();
31
}
32
33
$new = array($this->getCapabilityName() => $value);
34
$current_value[$phid]['policy'] = $new + $current_value[$phid]['policy'];
35
36
$editor = $this->getEditor();
37
$content_source = $editor->getContentSource();
38
39
// NOTE: We allow applications to have custom edit policies, but they are
40
// currently stored in the Config application. The ability to edit Config
41
// values is always restricted to administrators, today. Empower this
42
// particular edit to punch through possible stricter policies, so normal
43
// users can change application configuration if the application allows
44
// them to do so.
45
46
PhabricatorConfigEditor::storeNewValue(
47
PhabricatorUser::getOmnipotentUser(),
48
$config_entry,
49
$current_value,
50
$content_source,
51
$user->getPHID());
52
}
53
54
public function getTitle() {
55
return pht(
56
'%s changed the %s policy from %s to %s.',
57
$this->renderAuthor(),
58
$this->renderCapability(),
59
$this->renderOldPolicy(),
60
$this->renderNewPolicy());
61
}
62
63
public function getTitleForFeed() {
64
return pht(
65
'%s changed the %s policy for application %s from %s to %s.',
66
$this->renderAuthor(),
67
$this->renderCapability(),
68
$this->renderObject(),
69
$this->renderOldPolicy(),
70
$this->renderNewPolicy());
71
}
72
73
public function validateTransactions($object, array $xactions) {
74
$user = $this->getActor();
75
$application = $object;
76
$policies = id(new PhabricatorPolicyQuery())
77
->setViewer($user)
78
->setObject($application)
79
->execute();
80
81
$errors = array();
82
foreach ($xactions as $xaction) {
83
$new = $xaction->getNewValue();
84
$capability = $xaction->getMetadataValue(self::METADATA_ATTRIBUTE);
85
86
if (empty($policies[$new])) {
87
// Not a standard policy, check for a custom policy.
88
$policy = id(new PhabricatorPolicyQuery())
89
->setViewer($user)
90
->withPHIDs(array($new))
91
->executeOne();
92
if (!$policy) {
93
$errors[] = $this->newInvalidError(
94
pht('Policy does not exist.'));
95
continue;
96
}
97
} else {
98
$policy = idx($policies, $new);
99
}
100
101
if (!$policy->isValidPolicyForEdit()) {
102
$errors[] = $this->newInvalidError(
103
pht('Can\'t set the policy to a policy you can\'t view!'));
104
continue;
105
}
106
107
if ($new == PhabricatorPolicies::POLICY_PUBLIC) {
108
$capobj = PhabricatorPolicyCapability::getCapabilityByKey(
109
$capability);
110
if (!$capobj || !$capobj->shouldAllowPublicPolicySetting()) {
111
$errors[] = $this->newInvalidError(
112
pht('Can\'t set non-public policies to public.'));
113
continue;
114
}
115
}
116
117
if (!$application->isCapabilityEditable($capability)) {
118
$errors[] = $this->newInvalidError(
119
pht('Capability "%s" is not editable for this application.',
120
$capability));
121
continue;
122
}
123
}
124
125
// If we're changing these policies, the viewer needs to still be able to
126
// view or edit the application under the new policy.
127
$validate_map = array(
128
PhabricatorPolicyCapability::CAN_VIEW,
129
PhabricatorPolicyCapability::CAN_EDIT,
130
);
131
$validate_map = array_fill_keys($validate_map, array());
132
133
foreach ($xactions as $xaction) {
134
$capability = $xaction->getMetadataValue(self::METADATA_ATTRIBUTE);
135
if (!isset($validate_map[$capability])) {
136
continue;
137
}
138
139
$validate_map[$capability][] = $xaction;
140
}
141
142
foreach ($validate_map as $capability => $cap_xactions) {
143
if (!$cap_xactions) {
144
continue;
145
}
146
147
$editor = $this->getEditor();
148
$policy_errors = $editor->validatePolicyTransaction(
149
$object,
150
$cap_xactions,
151
self::TRANSACTIONTYPE,
152
$capability);
153
154
foreach ($policy_errors as $error) {
155
$errors[] = $error;
156
}
157
}
158
159
return $errors;
160
}
161
162
private function renderCapability() {
163
$application = $this->getObject();
164
$capability = $this->getCapabilityName();
165
$label = $application->getCapabilityLabel($capability);
166
return $this->renderValue($label);
167
}
168
169
private function getCapabilityName() {
170
return $this->getMetadataValue(self::METADATA_ATTRIBUTE);
171
}
172
173
}
174
175