1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @package midcom |
4
|
|
|
* @author The Midgard Project, http://www.midgard-project.org |
5
|
|
|
* @copyright The Midgard Project, http://www.midgard-project.org |
6
|
|
|
* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Privilege class, used to interact with the privilege system. It encapsulates the actual |
11
|
|
|
* Database Level Object. As usual with MidCOM DBA, you <i>must never access the DB layer |
12
|
|
|
* object.</i> |
13
|
|
|
* |
14
|
|
|
* The main area of expertise of this class is privilege IO (loading and storing), their |
15
|
|
|
* validation and privilege merging. |
16
|
|
|
* |
17
|
|
|
* It is important to understand that you must never load privilege records directly, or |
18
|
|
|
* access them by their IDs. Instead, use the DBA level interface functions to locate |
19
|
|
|
* existing privilege sets. The only time where you use this class directly is when |
20
|
|
|
* creating new privilege, using the default constructor of this class (although the |
21
|
|
|
* create_new_privilege_object DBA member methods are the preferred way of doing this). |
22
|
|
|
* |
23
|
|
|
* <b>Caching:</b> |
24
|
|
|
* |
25
|
|
|
* This class uses the memcache cache module to speed up ACL accesses. It caches the ACL |
26
|
|
|
* objects retrieved from the database, not any merged privilege set (at this time, that is). |
27
|
|
|
* This should speed up regular operations quite a bit (along with the parent guid cache, |
28
|
|
|
* which is a second important key). |
29
|
|
|
* |
30
|
|
|
* @property string $objectguid GUID of the object the privilege applies to |
31
|
|
|
* @property string $privilegename Name of the privilege (for example `midgard:create`) |
32
|
|
|
* @property string $assignee Assignee of the privilege, for instance user or group identifier |
33
|
|
|
* @property string $classname MgdSchema class the privilege applies to, in case of class-level privileges |
34
|
|
|
* @property integer $value |
35
|
|
|
Value of the privilege: |
36
|
|
|
|
37
|
|
|
- 1: MIDCOM_PRIVILEGE_ALLOW |
38
|
|
|
- 2: MIDCOM_PRIVILEGE_DENY |
39
|
|
|
- 3: MIDCOM_PRIVILEGE_INHERIT |
40
|
|
|
|
41
|
|
|
* @property string $guid |
42
|
|
|
* @package midcom |
43
|
|
|
*/ |
44
|
|
|
class midcom_core_privilege |
45
|
|
|
{ |
46
|
|
|
/** |
47
|
|
|
* Cached actual midcom_core_privilege_db data for this privilege. |
48
|
|
|
*/ |
49
|
|
|
private array $__privilege = [ |
50
|
|
|
'guid' => '', |
51
|
|
|
'objectguid' => '', |
52
|
|
|
'privilegename'=> '', |
53
|
|
|
'assignee' => null, |
54
|
|
|
'scope' => -1, |
55
|
|
|
'classname' => '', |
56
|
|
|
'value' => null |
57
|
|
|
]; |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* The actual object for this privilege. |
61
|
|
|
*/ |
62
|
|
|
private ?midcom_core_privilege_db $__privilege_object = null; |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* GUID of the midcom_core_privilege_db object, used when values are retrieved via collector instead of QB |
66
|
|
|
*/ |
67
|
|
|
private string $__guid = ''; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Cached content object, based on $objectguid. |
71
|
|
|
*/ |
72
|
|
|
private ?midcom_core_dbaobject $__cached_object = null; |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* The Default constructor creates an empty privilege, if you specify |
76
|
|
|
* another privilege object in the constructor, a copy is constructed. |
77
|
|
|
*/ |
78
|
134 |
|
public function __construct(midcom_core_privilege_db|array|string|null $src = null) |
79
|
|
|
{ |
80
|
134 |
|
if (is_array($src)) { |
81
|
|
|
// Store given values to our privilege array |
82
|
81 |
|
$this->__privilege = array_merge($this->__privilege, $src); |
83
|
|
|
} else { |
84
|
129 |
|
$this->_load($src); |
85
|
129 |
|
if ($src !== null) { |
|
|
|
|
86
|
25 |
|
$this->_sync_from_db_object(); |
87
|
|
|
} |
88
|
|
|
} |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
// Magic getter and setter for object property mapping |
92
|
139 |
|
public function __get($property) |
93
|
|
|
{ |
94
|
139 |
|
return $this->__privilege[$property] ?? null; |
95
|
|
|
} |
96
|
|
|
|
97
|
129 |
|
public function __set($property, $value) |
98
|
|
|
{ |
99
|
129 |
|
$this->__privilege[$property] = $value; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
public function __isset($property) |
103
|
|
|
{ |
104
|
|
|
return isset($this->__privilege[$property]); |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Get the object referenced by the guid value of this privilege. |
109
|
|
|
*/ |
110
|
125 |
|
private function get_object() : ?midcom_core_dbaobject |
111
|
|
|
{ |
112
|
125 |
|
if ($this->__cached_object === null) { |
113
|
|
|
try { |
114
|
25 |
|
$this->__cached_object = midcom::get()->dbfactory->get_object_by_guid($this->objectguid); |
115
|
|
|
} catch (midcom_error) { |
116
|
|
|
return null; |
117
|
|
|
} |
118
|
|
|
} |
119
|
125 |
|
return $this->__cached_object; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Set a privilege to a given content object. |
124
|
|
|
*/ |
125
|
129 |
|
public function set_object(midcom_core_dbaobject $object) |
126
|
|
|
{ |
127
|
129 |
|
$this->__cached_object = $object; |
128
|
129 |
|
$this->objectguid = $object->guid; |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* Determine whether a given privilege applies for the given |
133
|
|
|
* user in content mode. This means, that all SELF privileges are skipped at this point, |
134
|
|
|
* EVERYONE privileges apply always, and all other privileges are checked against the |
135
|
|
|
* user. |
136
|
|
|
*/ |
137
|
81 |
|
public function does_privilege_apply(string $user_id) : bool |
138
|
|
|
{ |
139
|
81 |
|
switch ($this->__privilege['assignee']) { |
140
|
81 |
|
case 'EVERYONE': |
141
|
|
|
return true; |
142
|
81 |
|
case 'ANONYMOUS': |
143
|
|
|
return in_array($user_id, ['EVERYONE', 'ANONYMOUS']); |
144
|
81 |
|
case 'USERS': |
145
|
|
|
return !in_array($user_id, ['EVERYONE', 'ANONYMOUS']); |
146
|
|
|
default: |
147
|
81 |
|
if ($this->__privilege['assignee'] == $user_id) { |
148
|
51 |
|
return true; |
149
|
|
|
} |
150
|
36 |
|
if (str_starts_with($this->__privilege['assignee'], 'group:')) { |
151
|
1 |
|
if ($user = midcom::get()->auth->get_user($user_id)) { |
152
|
1 |
|
return $user->is_in_group($this->__privilege['assignee']); |
153
|
|
|
} |
154
|
|
|
} |
155
|
36 |
|
return false; |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* Returns the privilege's scope (or -1 for SELF and broken privileges) |
161
|
|
|
*/ |
162
|
81 |
|
public function get_scope() : int |
163
|
|
|
{ |
164
|
81 |
|
if (defined('MIDCOM_PRIVILEGE_SCOPE_' . $this->__privilege['assignee'])) { |
165
|
|
|
return constant('MIDCOM_PRIVILEGE_SCOPE_' . $this->__privilege['assignee']); |
166
|
|
|
} |
167
|
81 |
|
if ($assignee = $this->get_assignee()) { |
168
|
81 |
|
return $assignee->scope; |
169
|
|
|
} |
170
|
|
|
debug_print_r('Could not resolve the assignee of this privilege', $this); |
171
|
|
|
|
172
|
|
|
return -1; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* If the assignee has an object representation (at this time, only users and groups have), this call |
177
|
|
|
* will return the assignee object held by the authentication service. |
178
|
|
|
* |
179
|
|
|
* Use is_magic_assignee to determine if you have an assignee object. |
180
|
|
|
* |
181
|
|
|
* @see midcom_services_auth::get_assignee() |
182
|
|
|
* @return midcom_core_user|midcom_core_group|null object as returned by the auth service, null on failure. |
183
|
|
|
*/ |
184
|
131 |
|
public function get_assignee() : ?object |
185
|
|
|
{ |
186
|
131 |
|
if ($this->is_magic_assignee()) { |
187
|
|
|
return null; |
188
|
|
|
} |
189
|
|
|
|
190
|
131 |
|
return midcom::get()->auth->get_assignee($this->assignee); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Checks whether the current assignee is a magic assignee or an object identifier. |
195
|
|
|
*/ |
196
|
136 |
|
public function is_magic_assignee(?string $assignee = null) : bool |
197
|
|
|
{ |
198
|
136 |
|
$assignee ??= $this->assignee; |
199
|
136 |
|
return in_array($assignee, ['SELF', 'EVERYONE', 'USERS', 'ANONYMOUS', 'OWNER']); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* Set the assignee member string to the correct value to represent the |
204
|
|
|
* object passed, in general, this resolves users and groups to their strings and |
205
|
|
|
* leaves magic assignees intact. |
206
|
|
|
* |
207
|
|
|
* Possible argument types: |
208
|
|
|
* |
209
|
|
|
* - Any one of the magic assignees SELF, EVERYONE, ANONYMOUS, USERS. |
210
|
|
|
* - Any midcom_core_user or midcom_core_group object or subtype thereof. |
211
|
|
|
* - Any string identifier which can be resolved using midcom_services_auth::get_assignee(). |
212
|
|
|
*/ |
213
|
129 |
|
public function set_assignee(midcom_core_group|midcom_core_user|string $assignee) : bool |
214
|
|
|
{ |
215
|
129 |
|
if (is_string($assignee)) { |
216
|
129 |
|
if ($this->is_magic_assignee($assignee)) { |
217
|
12 |
|
$this->assignee = $assignee; |
218
|
|
|
} else { |
219
|
126 |
|
$tmp = midcom::get()->auth->get_assignee($assignee); |
220
|
126 |
|
if (!$tmp) { |
221
|
|
|
debug_add("Could not resolve the assignee string '{$assignee}', see above for more information.", MIDCOM_LOG_INFO); |
222
|
|
|
return false; |
223
|
|
|
} |
224
|
129 |
|
$this->assignee = $tmp->id; |
225
|
|
|
} |
226
|
|
|
} else { |
227
|
1 |
|
$this->assignee = $assignee->id; |
228
|
|
|
} |
229
|
|
|
|
230
|
129 |
|
return true; |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* Validate the privilege for correctness of all set options. This includes: |
235
|
|
|
* |
236
|
|
|
* - A check against the list of registered privileges to ensure the existence of the |
237
|
|
|
* privilege itself. |
238
|
|
|
* - A check for a valid and existing assignee, this includes a class existence check for classname restrictions |
239
|
|
|
* for SELF privileges. |
240
|
|
|
* - A check for an existing content object GUID (this implicitly checks for midgard:read as well). |
241
|
|
|
* - Enough privileges of the current user to update the object's privileges (the user |
242
|
|
|
* must have midgard:update and midgard:privileges for this to succeed). |
243
|
|
|
* - A valid privilege value. |
244
|
|
|
*/ |
245
|
125 |
|
public function validate() : bool |
246
|
|
|
{ |
247
|
125 |
|
if (!midcom::get()->auth->acl->privilege_exists($this->privilegename)) { |
248
|
|
|
debug_add("The privilege name '{$this->privilegename}' is unknown to the system. Perhaps the corresponding component is not loaded?", |
249
|
|
|
MIDCOM_LOG_INFO); |
250
|
|
|
return false; |
251
|
|
|
} |
252
|
|
|
|
253
|
125 |
|
if (!in_array($this->value, [MIDCOM_PRIVILEGE_ALLOW, MIDCOM_PRIVILEGE_DENY, MIDCOM_PRIVILEGE_INHERIT])) { |
254
|
|
|
debug_add("Invalid privilege value '{$this->value}'.", MIDCOM_LOG_INFO); |
255
|
|
|
return false; |
256
|
|
|
} |
257
|
|
|
|
258
|
125 |
|
if ($this->classname != '') { |
259
|
1 |
|
if ($this->assignee != 'SELF') { |
260
|
|
|
debug_add("The classname parameter was specified without having the magic assignee SELF set, this is invalid.", MIDCOM_LOG_INFO); |
261
|
|
|
return false; |
262
|
|
|
} |
263
|
1 |
|
if (!class_exists($this->classname)) { |
264
|
|
|
debug_add("The class '{$this->classname}' is not found, the SELF magic assignee with class restriction is invalid therefore.", MIDCOM_LOG_INFO); |
265
|
|
|
return false; |
266
|
|
|
} |
267
|
|
|
} |
268
|
|
|
|
269
|
125 |
|
if ( !$this->is_magic_assignee() |
270
|
125 |
|
&& !$this->get_assignee()) { |
271
|
|
|
debug_add("The assignee identifier '{$this->assignee}' is invalid.", MIDCOM_LOG_INFO); |
272
|
|
|
return false; |
273
|
|
|
} |
274
|
125 |
|
if ( $this->assignee == 'OWNER' |
275
|
125 |
|
&& $this->privilegename == 'midgard:owner') { |
276
|
|
|
debug_add("Tried to assign midgard:owner to the OWNER magic assignee, this is invalid.", MIDCOM_LOG_INFO); |
277
|
|
|
return false; |
278
|
|
|
} |
279
|
|
|
|
280
|
125 |
|
$object = $this->get_object(); |
281
|
125 |
|
if (!$object) { |
282
|
|
|
debug_add("Could not retrieve the content object with the GUID '{$this->objectguid}'; see the debug level log for more information.", |
283
|
|
|
MIDCOM_LOG_INFO); |
284
|
|
|
return false; |
285
|
|
|
} |
286
|
125 |
|
if ( !$object->can_do('midgard:update') |
287
|
125 |
|
|| !$object->can_do('midgard:privileges')) { |
288
|
|
|
debug_add("Insufficient privileges on the content object with the GUID '{$this->__guid}', midgard:update and midgard:privileges required.", |
289
|
|
|
MIDCOM_LOG_INFO); |
290
|
|
|
return false; |
291
|
|
|
} |
292
|
|
|
|
293
|
125 |
|
return true; |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
/** |
297
|
|
|
* List all content privileges assigned to a given object. |
298
|
|
|
* Essentially, this will exclude all SELF style assignees. |
299
|
|
|
* |
300
|
|
|
* This function is for use in the authentication framework only. |
301
|
|
|
* |
302
|
|
|
* @return midcom_core_privilege[] |
303
|
|
|
*/ |
304
|
133 |
|
public static function get_content_privileges(string $guid) : array |
305
|
|
|
{ |
306
|
133 |
|
return self::_get_privileges($guid, 'CONTENT'); |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
/** |
310
|
|
|
* List all privileges assigned directly to a user or group. |
311
|
|
|
* These are all SELF privileges. |
312
|
|
|
* |
313
|
|
|
* This function is for use in the authentication framework only. |
314
|
|
|
* |
315
|
|
|
* @return midcom_core_privilege[] |
316
|
|
|
*/ |
317
|
14 |
|
public static function get_self_privileges(string $guid) : array |
318
|
|
|
{ |
319
|
14 |
|
return self::_get_privileges($guid, 'SELF'); |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
/** |
323
|
|
|
* List all privileges assigned an object unfiltered. |
324
|
|
|
* |
325
|
|
|
* This function is for use in the authentication framework only |
326
|
|
|
* |
327
|
|
|
* @return midcom_core_privilege[] |
328
|
|
|
*/ |
329
|
1 |
|
public static function get_all_privileges(string $guid) : array |
330
|
|
|
{ |
331
|
1 |
|
return array_merge(self::get_content_privileges($guid), self::get_self_privileges($guid)); |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* List all privileges assigned an object unfiltered. |
336
|
|
|
* |
337
|
|
|
* @return midcom_core_privilege[] |
338
|
|
|
*/ |
339
|
134 |
|
private static function _get_privileges(string $guid, string $type) : array |
340
|
|
|
{ |
341
|
134 |
|
static $cache = []; |
342
|
|
|
|
343
|
134 |
|
$cache_key = $type . '-' . $guid; |
344
|
|
|
|
345
|
134 |
|
if (!array_key_exists($cache_key, $cache)) { |
346
|
132 |
|
$return = midcom::get()->cache->memcache->get('ACL', $cache_key); |
347
|
|
|
|
348
|
132 |
|
if (!is_array($return)) { |
349
|
|
|
// Didn't get privileges from cache, get them from DB |
350
|
132 |
|
$return = self::_query_privileges($guid, $type); |
351
|
132 |
|
midcom::get()->cache->memcache->put('ACL', $cache_key, $return); |
352
|
|
|
} |
353
|
|
|
|
354
|
132 |
|
$cache[$cache_key] = $return; |
355
|
|
|
} |
356
|
|
|
|
357
|
134 |
|
return $cache[$cache_key]; |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* Query the database for privileges and construct all necessary objects out of it. |
362
|
|
|
* |
363
|
|
|
* @param string $type SELF or CONTENT |
364
|
|
|
* @return midcom_core_privilege[] |
365
|
|
|
*/ |
366
|
132 |
|
protected static function _query_privileges(string $guid, string $type) : array |
367
|
|
|
{ |
368
|
132 |
|
$result = []; |
369
|
|
|
|
370
|
132 |
|
$mc = new midgard_collector('midcom_core_privilege_db', 'objectguid', $guid); |
371
|
132 |
|
$mc->add_constraint('value', '<>', MIDCOM_PRIVILEGE_INHERIT); |
372
|
|
|
|
373
|
132 |
|
if ($type == 'CONTENT') { |
374
|
128 |
|
$mc->add_constraint('assignee', 'NOT IN', ['SELF', '']); |
375
|
|
|
} else { |
376
|
14 |
|
$mc->add_constraint('assignee', '=', 'SELF'); |
377
|
|
|
} |
378
|
|
|
|
379
|
132 |
|
$mc->set_key_property('guid'); |
380
|
132 |
|
$mc->add_value_property('id'); |
381
|
132 |
|
$mc->add_value_property('privilegename'); |
382
|
132 |
|
$mc->add_value_property('assignee'); |
383
|
132 |
|
$mc->add_value_property('classname'); |
384
|
132 |
|
$mc->add_value_property('value'); |
385
|
132 |
|
$mc->execute(); |
386
|
132 |
|
$privileges = $mc->list_keys(); |
387
|
|
|
|
388
|
132 |
|
foreach (array_keys($privileges) as $privilege_guid) { |
389
|
80 |
|
$privilege = $mc->get($privilege_guid); |
390
|
80 |
|
$privilege['objectguid'] = $guid; |
391
|
80 |
|
$privilege['guid'] = $privilege_guid; |
392
|
80 |
|
$privilege_object = new static($privilege); |
393
|
80 |
|
$result[] = $privilege_object; |
394
|
|
|
} |
395
|
|
|
|
396
|
132 |
|
return $result; |
397
|
|
|
} |
398
|
|
|
|
399
|
|
|
/** |
400
|
|
|
* Retrieve a single given privilege at a content object, identified by |
401
|
|
|
* the combination of assignee and privilege name. |
402
|
|
|
* |
403
|
|
|
* This call will return an object even if the privilege is set to INHERITED at |
404
|
|
|
* the given object (i.e. does not exist) for consistency reasons. Errors are |
405
|
|
|
* thrown for example on database inconsistencies. |
406
|
|
|
* |
407
|
|
|
* This function is for use in the authentication framework only. |
408
|
|
|
* |
409
|
|
|
* @param string $classname The optional classname required only for class-limited SELF privileges. |
410
|
|
|
*/ |
411
|
129 |
|
public static function get_privilege(midcom_core_dbaobject $object, string $name, string $assignee, string $classname = '') : midcom_core_privilege |
412
|
|
|
{ |
413
|
129 |
|
$qb = new midgard_query_builder('midcom_core_privilege_db'); |
414
|
129 |
|
$qb->add_constraint('objectguid', '=', $object->guid); |
415
|
129 |
|
$qb->add_constraint('privilegename', '=', $name); |
416
|
129 |
|
$qb->add_constraint('assignee', '=', $assignee); |
417
|
129 |
|
$qb->add_constraint('classname', '=', $classname); |
418
|
129 |
|
$result = $qb->execute(); |
419
|
|
|
|
420
|
129 |
|
if (empty($result)) { |
421
|
|
|
// No such privilege stored, return non-persistent one |
422
|
121 |
|
$privilege = new self; |
423
|
121 |
|
$privilege->set_object($object); |
424
|
121 |
|
$privilege->set_assignee($assignee); |
425
|
121 |
|
$privilege->privilegename = $name; |
426
|
121 |
|
$privilege->classname = $classname; |
427
|
121 |
|
$privilege->value = MIDCOM_PRIVILEGE_INHERIT; |
428
|
121 |
|
return $privilege; |
429
|
|
|
} |
430
|
25 |
|
if (count($result) > 1) { |
431
|
|
|
debug_add('A DB inconsistency has been detected. There is more than one record for privilege specified. Deleting all excess records after the first one!', |
432
|
|
|
MIDCOM_LOG_ERROR); |
433
|
|
|
debug_print_r('Content Object:', $object); |
434
|
|
|
debug_add("Privilege {$name} for assignee {$assignee} with classname {$classname} was queried.", MIDCOM_LOG_INFO); |
435
|
|
|
debug_print_r('Resultset was:', $result); |
436
|
|
|
midcom::get()->auth->request_sudo('midcom.core'); |
437
|
|
|
while (count($result) > 1) { |
438
|
|
|
$privilege = array_pop($result); |
439
|
|
|
$privilege->purge(); |
440
|
|
|
} |
441
|
|
|
midcom::get()->auth->drop_sudo(); |
442
|
|
|
} |
443
|
|
|
|
444
|
25 |
|
return new midcom_core_privilege($result[0]); |
445
|
|
|
} |
446
|
|
|
|
447
|
129 |
|
private function _load(midcom_core_privilege_db|string|null $src = null) |
448
|
|
|
{ |
449
|
129 |
|
if ($src instanceof midcom_core_privilege_db) { |
450
|
|
|
// Got a privilege object as argument, use that |
451
|
25 |
|
$this->__guid = $src->guid; |
452
|
25 |
|
$this->__privilege_object = $src; |
453
|
129 |
|
} elseif (is_string($src) && mgd_is_guid($src)) { |
454
|
|
|
$this->__guid = $src; |
455
|
|
|
$this->__privilege_object = new midcom_core_privilege_db($src); |
456
|
|
|
} else { |
457
|
|
|
// Have a nonpersistent privilege |
458
|
129 |
|
$this->__privilege_object = new midcom_core_privilege_db(); |
459
|
|
|
} |
460
|
|
|
} |
461
|
|
|
|
462
|
125 |
|
private function _sync_to_db_object() |
463
|
|
|
{ |
464
|
125 |
|
if (!$this->__privilege_object) { |
465
|
1 |
|
$this->_load($this->guid); |
466
|
|
|
} |
467
|
125 |
|
$this->__privilege_object->objectguid = $this->objectguid; |
468
|
125 |
|
$this->__privilege_object->privilegename = $this->privilegename; |
469
|
125 |
|
$this->__privilege_object->assignee = $this->assignee; |
470
|
125 |
|
$this->__privilege_object->classname = $this->classname; |
471
|
125 |
|
$this->__privilege_object->value = $this->value; |
472
|
|
|
} |
473
|
|
|
|
474
|
25 |
|
private function _sync_from_db_object() |
475
|
|
|
{ |
476
|
25 |
|
$this->objectguid = $this->__privilege_object->objectguid; |
477
|
25 |
|
$this->privilegename = $this->__privilege_object->privilegename; |
478
|
25 |
|
$this->assignee = $this->__privilege_object->assignee; |
479
|
25 |
|
$this->classname = $this->__privilege_object->classname; |
480
|
25 |
|
$this->value = $this->__privilege_object->value; |
481
|
25 |
|
$this->guid = $this->__privilege_object->guid; |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
/** |
485
|
|
|
* Store the privilege. This will validate it first and then either |
486
|
|
|
* update an existing privilege record, or create a new one, depending on the |
487
|
|
|
* DB state. |
488
|
|
|
*/ |
489
|
125 |
|
public function store() : bool |
490
|
|
|
{ |
491
|
125 |
|
if (!$this->validate()) { |
492
|
|
|
debug_add('This privilege failed to validate, rejecting it, see the debug log for details.', MIDCOM_LOG_WARN); |
493
|
|
|
$this->__cached_object = null; |
494
|
|
|
debug_print_r('Privilege dump (w/o cached object):', $this); |
495
|
|
|
return false; |
496
|
|
|
} |
497
|
|
|
|
498
|
125 |
|
$this->_sync_to_db_object(); |
499
|
|
|
|
500
|
125 |
|
if ($this->value == MIDCOM_PRIVILEGE_INHERIT) { |
501
|
|
|
if ($this->__guid) { |
502
|
|
|
// Already a persistent record, drop it. |
503
|
|
|
return $this->drop(); |
504
|
|
|
} |
505
|
|
|
// This is a temporary object only, try to load the real object first. If it is not found, |
506
|
|
|
// exit silently, as this is the desired final state. |
507
|
|
|
$object = $this->get_object(); |
508
|
|
|
$privilege = self::get_privilege($object, $this->privilegename, $this->assignee, $this->classname); |
509
|
|
|
if (!empty($privilege->__guid)) { |
510
|
|
|
if (!$privilege->drop()) { |
511
|
|
|
return false; |
512
|
|
|
} |
513
|
|
|
$this->_invalidate_cache(); |
514
|
|
|
} |
515
|
|
|
return true; |
516
|
|
|
} |
517
|
|
|
|
518
|
125 |
|
if ($this->__guid) { |
519
|
20 |
|
if (!$this->__privilege_object->update()) { |
520
|
|
|
return false; |
521
|
|
|
} |
522
|
20 |
|
$this->_invalidate_cache(); |
523
|
20 |
|
return true; |
524
|
|
|
} |
525
|
|
|
|
526
|
125 |
|
$object = $this->get_object(); |
527
|
125 |
|
$privilege = self::get_privilege($object, $this->privilegename, $this->assignee, $this->classname); |
528
|
125 |
|
if (!empty($privilege->__guid)) { |
529
|
20 |
|
$privilege->value = $this->value; |
530
|
20 |
|
if (!$privilege->store()) { |
531
|
|
|
debug_add('Update of the existing privilege failed.', MIDCOM_LOG_WARN); |
532
|
|
|
return false; |
533
|
|
|
} |
534
|
20 |
|
$this->__guid = $privilege->__guid; |
535
|
20 |
|
$this->objectguid = $privilege->objectguid; |
536
|
20 |
|
$this->privilegename = $privilege->privilegename; |
537
|
20 |
|
$this->assignee = $privilege->assignee; |
538
|
20 |
|
$this->classname = $privilege->classname; |
539
|
20 |
|
$this->value = $privilege->value; |
540
|
|
|
|
541
|
20 |
|
$this->_invalidate_cache(); |
542
|
20 |
|
return true; |
543
|
|
|
} |
544
|
|
|
|
545
|
117 |
|
if (!$this->__privilege_object->create()) { |
546
|
|
|
debug_add('Creating new privilege failed: ' . midcom_connection::get_error_string(), MIDCOM_LOG_WARN); |
547
|
|
|
return false; |
548
|
|
|
} |
549
|
117 |
|
$this->__guid = $this->__privilege_object->guid; |
550
|
117 |
|
$this->_invalidate_cache(); |
551
|
117 |
|
return true; |
552
|
|
|
} |
553
|
|
|
|
554
|
|
|
/** |
555
|
|
|
* Invalidate the memcache after I/O operations |
556
|
|
|
*/ |
557
|
125 |
|
private function _invalidate_cache() |
558
|
|
|
{ |
559
|
125 |
|
midcom::get()->cache->invalidate($this->objectguid); |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
/** |
563
|
|
|
* Drop the privilege. If we are a known DB record, we delete us, otherwise |
564
|
|
|
* we return silently. |
565
|
|
|
*/ |
566
|
9 |
|
public function drop() : bool |
567
|
|
|
{ |
568
|
9 |
|
$this->_sync_to_db_object(); |
569
|
|
|
|
570
|
9 |
|
if (!$this->__guid) { |
571
|
3 |
|
debug_add('We are not stored, GUID is empty. Ignoring silently.'); |
572
|
3 |
|
return true; |
573
|
|
|
} |
574
|
|
|
|
575
|
7 |
|
if (!$this->validate()) { |
576
|
|
|
debug_add('This privilege failed to validate, rejecting to drop it, see the debug log for details.', MIDCOM_LOG_WARN); |
577
|
|
|
debug_print_r('Privilege dump:', $this); |
578
|
|
|
return false; |
579
|
|
|
} |
580
|
|
|
|
581
|
7 |
|
if (!$this->__privilege_object->guid) { |
582
|
|
|
// We created this via collector, instantiate a new one |
583
|
|
|
$privilege = new midcom_core_privilege($this->__guid); |
584
|
|
|
return $privilege->drop(); |
585
|
|
|
} |
586
|
|
|
|
587
|
7 |
|
if (!$this->__privilege_object->purge()) { |
588
|
|
|
debug_add('Failed to delete privilege record, aborting. Error: ' . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); |
589
|
|
|
return false; |
590
|
|
|
} |
591
|
|
|
|
592
|
7 |
|
debug_add("Deleted privilege record {$this->__guid} ({$this->__privilege_object->objectguid} {$this->__privilege_object->privilegename} {$this->__privilege_object->assignee} {$this->__privilege_object->value}"); |
593
|
|
|
|
594
|
7 |
|
$this->_invalidate_cache(); |
595
|
7 |
|
$this->value = MIDCOM_PRIVILEGE_INHERIT; |
596
|
|
|
|
597
|
7 |
|
return true; |
598
|
|
|
} |
599
|
|
|
} |
600
|
|
|
|