class_aclAssignment.inc 10.4 KB
Newer Older
Côme Bernigaud's avatar
Côme Bernigaud committed
1
2
3
<?php
/*
  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
4
  Copyright (C) 2013-2016  FusionDirectory
Côme Bernigaud's avatar
Côme Bernigaud committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/

class aclAssignmentDialogWindow extends simplePlugin
{
  static function plInfo()
  {
    return array(
26
      'plShortName'   => _('ACL Assignment Dialog'),
Côme Bernigaud's avatar
Côme Bernigaud committed
27
28
29
      'plDescription' => _('Access control roles assignment dialog'),
      'plCategory'    => array('acl'),

30
      'plProvidedAcls' => parent::generatePlProvidedAcls(static::getAttributesInfo())
Côme Bernigaud's avatar
Côme Bernigaud committed
31
32
33
34
35
36
37
38
39
40
41
42
    );
  }

  static function getAttributesInfo()
  {
    return array(
      'properties' => array(
        'name'  => _('Properties'),
        'attrs' => array(
          new SelectAttribute(
            _('Mode'), _('Is this applying on complete subtree or only the base?'),
            'aclMode', TRUE,
43
            array('subtree',    'base'), 'base',
Côme Bernigaud's avatar
Côme Bernigaud committed
44
45
46
47
48
49
50
51
52
            array(_('Subtree'), _('Base only'))
          ),
          new SelectAttribute(
            _('Role'), _('Role to apply'),
            'aclRole', TRUE,
            array()
          ),
          new BooleanAttribute(
            _('For all users'), _('Apply this ACL for all LDAP users'),
53
            'allUsers', FALSE
Côme Bernigaud's avatar
Côme Bernigaud committed
54
          ),
55
          new UsersGroupsRolesAttribute(
Côme Bernigaud's avatar
Côme Bernigaud committed
56
57
58
59
60
61
62
63
            _('Members'), _('Users or groups to assign this role to.'),
            'aclMembers', TRUE
          )
        )
      ),
    );
  }

64
  function __construct ($value, $isContainer = FALSE)
Côme Bernigaud's avatar
Côme Bernigaud committed
65
  {
66
    parent::__construct(NULL, NULL, NULL, TRUE);
67
68
69
70
71
72
73
    if ($isContainer) {
      $this->attributesAccess['aclMode']->setDefaultValue('subtree');
    } else {
      $this->attributesAccess['aclMode']->setDefaultValue('base');
    }
    $this->attributesAccess['aclMode']->resetToDefault();

Côme Bernigaud's avatar
Côme Bernigaud committed
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    $roles = objects::ls('aclRole', 'cn');
    $this->attributesAccess['aclRole']->setChoices(array_keys($roles), array_values($roles));
    $this->attributesAccess['allUsers']->setInLdap(FALSE);
    $this->attributesAccess['allUsers']->setManagedAttributes(
      array(
        'disable' => array(
          TRUE => array('aclMembers')
        )
      )
    );

    if ($value !== NULL) {
      $this->aclMode    = $value['scope'];
      $this->aclRole    = $value['role'];
      $this->aclMembers = $value['members'];
89
90
91
      if ($value['members'][0] == '*') {
        $this->allUsers = TRUE;
      }
Côme Bernigaud's avatar
Côme Bernigaud committed
92
93
94
95
96
97
98
99
    }
  }

  function execute()
  {
    $smarty = get_smarty();
    $display = parent::execute();
    if (!is_object($this->dialog)) {
100
101
102
103
104
105
      $display .= $smarty->fetch('string:'.
        '<p class="plugbottom">'.
        '  <input type="submit" name="add_acl_finish" value="{msgPool type=addButton}"/>'.
        '  &nbsp;'.
        '  <input type="submit" name="add_acl_cancel" value="{msgPool type=cancelButton}"/>'.
        '</p>');
Côme Bernigaud's avatar
Côme Bernigaud committed
106
107
108
109
110
111
112
113
114
115
116
117
    }
    return $display;
  }

  function getAclEntry()
  {
    $entry = array(
      'scope'   => $this->aclMode,
      'role'    => $this->aclRole,
      'members' => $this->aclMembers,
    );
    if ($this->allUsers) {
118
      $entry['members'] = array('*');
Côme Bernigaud's avatar
Côme Bernigaud committed
119
    }
120
    return $entry;
Côme Bernigaud's avatar
Côme Bernigaud committed
121
122
123
124
125
126
127
128
129
130
  }
}

class ACLsAssignmentDialog extends GenericDialog
{
  protected $initialAclValue;
  protected $post_cancel = 'add_acl_cancel';
  protected $post_finish = 'add_acl_finish';
  protected $dialogClass = 'aclAssignmentDialogWindow';

131
  function __construct($simplePlugin, $attribute, $acl = NULL)
Côme Bernigaud's avatar
Côme Bernigaud committed
132
  {
133
    $isContainer = FALSE;
134
135
136
137
138
139
140
141
    if (isset($simplePlugin->attrs['objectClass'])) {
      if (count(array_intersect(
                  $simplePlugin->attrs['objectClass'],
                  array('organizationalUnit', 'organization', 'domain', 'country', 'locality'))
                )) {
        $isContainer = TRUE;
      }
    } else {
142
143
      $isContainer = TRUE;
    }
Côme Bernigaud's avatar
Côme Bernigaud committed
144
    $this->attribute        = $attribute;
145
    $this->dialog           = new $this->dialogClass($acl, $isContainer);
Côme Bernigaud's avatar
Côme Bernigaud committed
146
147
148
149
150
151
152
153
154
155
156
157
    $this->dialog->set_acl_base($simplePlugin->acl_base);
    $this->initialAclValue  = $acl;
  }

  function dialog_execute ()
  {
    $this->dialog->save_object();
    return $this->dialog->execute();
  }

  function handle_finish ()
  {
158
    $this->dialog->save_object();
159
160
161
162
163
    $messages = $this->dialog->check();
    if (!empty($messages)) {
      msg_dialog::displayChecks($messages);
      return $this->dialog->execute();
    }
Côme Bernigaud's avatar
Côme Bernigaud committed
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
    $this->attribute->addValue($this->dialog->getAclEntry());
    return FALSE;
  }

  function handle_cancel ()
  {
    if ($this->initialAclValue !== NULL) {
      $this->attribute->addValue($this->initialAclValue);
    }
    return FALSE;
  }
}

class ACLsAssignmentAttribute extends DialogOrderedArrayAttribute
{
179
180
  protected $order        = TRUE;
  protected $dialogClass  = 'ACLsAssignmentDialog';
181
  protected $height       = 300;
Côme Bernigaud's avatar
Côme Bernigaud committed
182

183
  protected function getAttributeArrayValue($key, $value)
Côme Bernigaud's avatar
Côme Bernigaud committed
184
185
  {
    /* Convert text value to displayable array value */
186
187
188
189
190
191
192
    sort($value['members']);
    static $nbShown = 4;
    $members = join(', ', array_slice($value['members'], 0, $nbShown));
    if (count($value['members']) > $nbShown) {
      $members .= sprintf(_(', and %d others'), (count($value['members']) - $nbShown));
    }
    $value['members'] = $members;
Côme Bernigaud's avatar
Côme Bernigaud committed
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
    return $value;
  }

  function readValue($value)
  {
    $acl = explode(':', $value);
    return array($acl[0], array(
      'scope'   => $acl[1],
      'role'    => base64_decode($acl[2]),
      'members' => array_map('base64_decode', explode(',', $acl[3])),
    ));
  }

  function writeValue($key, $value)
  {
    return $key.':'.$value['scope'].':'.base64_encode($value['role']).':'.join(',', array_map('base64_encode', $value['members']));
  }
210
211
212
213

  function foreignKeyUpdate($oldvalue, $newvalue, $source)
  {
    foreach ($this->value as $key => &$value) {
214
      if (($source['CLASS'] == 'aclRole') && ($value['role'] == $oldvalue) && ($source['MODE'] != 'copy')) {
215
216
217
        if ($newvalue === NULL) {
          unset($this->value[$key]);
        } else {
218
          $value['role'] = $newvalue;
219
        }
220
      } elseif (in_array($source['CLASS'], array('user','group','roleGeneric')) && (($member_key = array_search($oldvalue, $value['members'])) !== FALSE)) {
221
        if ($newvalue === NULL) {
222
          unset($value['members'][$member_key]);
223
        } elseif ($source['MODE'] == 'move') {
224
          $value['members'][$member_key] = $newvalue;
225
226
        } elseif ($source['MODE'] == 'copy') {
          $value['members'][] = $newvalue;
227
        }
228
      } elseif (!in_array($source['CLASS'], array('aclRole','user','group','roleGeneric'))) {
229
        trigger_error('unknown source '.$source['CLASS']);
230
231
232
233
      }
    }
    unset($value);
  }
234
235
236

  function foreignKeyCheck($oldvalue, $source)
  {
237
    foreach ($this->value as $value) {
238
      if (($source['CLASS'] == 'aclRole') && ($value['role'] == $oldvalue)) {
239
        return TRUE;
240
      } elseif (in_array($source['CLASS'], array('user','group','roleGeneric')) && in_array($oldvalue, $value['members'])) {
241
        return TRUE;
242
      } elseif (!in_array($source['CLASS'], array('aclRole','user','group','roleGeneric'))) {
243
        trigger_error('unknown source '.$source['CLASS']);
244
245
246
      }
    }
  }
Côme Bernigaud's avatar
Côme Bernigaud committed
247
248
249
250
251
252
253
254
}

class aclAssignment extends simplePlugin
{
  var $objectclasses  = array('gosaAcl');

  static function plInfo()
  {
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
    global $config;
    $oc = array(
      'aclAssignment' => array(
        'aclCategory' => 'acl',
        'name'        => _('ACL assignment'),
        'filter'      => 'objectClass=gosaAcl',
        'ou'          => '',
        'icon'        => 'geticon.php?context=categories&icon=acl&size=16',
        'tabClass'    => 'simpleTabs_noSpecial',
        'mainAttr'    => FALSE
      ),
    );
    if ($config->get_cfg_value('aclTabOnObjects') == 'TRUE') {
      $oc[] = 'special';
    } else {
      $oc = array_merge($oc, departmentManagement::getDepartmentTypes());
    }
Côme Bernigaud's avatar
Côme Bernigaud committed
272
273
274
    return array(
      'plShortName'   => _('ACL Assignment'),
      'plDescription' => _('Access control roles assignment'),
275
      'plObjectType'  => $oc,
276
277
      'plForeignKeys'  => array(
        'gosaAclEntry' => array(
278
279
280
281
          array('aclRole',      'dn', 'gosaAclEntry=*:*:%b|oldvalue%:*'),
          array('user',         'dn', 'gosaAclEntry=*:*:*:*%b|oldvalue%*'),
          array('group',        'dn', 'gosaAclEntry=*:*:*:*%b|oldvalue%*'),
          array('roleGeneric',  'dn', 'gosaAclEntry=*:*:*:*%b|oldvalue%*'),
282
283
        )
      ),
Côme Bernigaud's avatar
Côme Bernigaud committed
284

285
      'plProvidedAcls' => parent::generatePlProvidedAcls(static::getAttributesInfo())
Côme Bernigaud's avatar
Côme Bernigaud committed
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
    );
  }

  static function getAttributesInfo()
  {
    return array(
      'main' => array(
        'name'  => _('Assignments'),
        'class' => array('fullwidth'),
        'attrs' => array(
          new ACLsAssignmentAttribute(
            '', _('ACL role assignments for this base'),
            'gosaAclEntry', FALSE
          )
        )
      )
    );
  }

305
  function __construct ($dn = NULL, $object = NULL, $parent = NULL, $mainTab = FALSE)
306
  {
307
    parent::__construct ($dn, $object, $parent, FALSE);
308
309
310
    $this->attributesInfo['main']['name'] = sprintf(_('Assignments on object or subtree %s'), $this->dn);
  }

Côme Bernigaud's avatar
Côme Bernigaud committed
311
312
313
314
315
  function compute_dn()
  {
    return $this->dn;
  }

316
  function save()
Côme Bernigaud's avatar
Côme Bernigaud committed
317
318
319
  {
    $this->ignore_account = FALSE;
    $this->is_account = (count($this->gosaAclEntry) != 0);
320
321
322
    if ($this->is_account) {
      return parent::save();
    } else {
323
      return $this->remove_from_parent();
324
    }
Côme Bernigaud's avatar
Côme Bernigaud committed
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
  }

  function post_remove()
  {
    parent::post_remove();

    /* Refresh users ACLs */
    $ui = get_userinfo();
    $ui->loadACL();
    session::global_set('ui', $ui);
  }

  function post_save()
  {
    parent::post_save();

    /* Refresh users ACLs */
    $ui = get_userinfo();
    $ui->loadACL();
    session::global_set('ui', $ui);
  }
346
347
348
349
350
351
352
353
354

  function foreignKeyUpdate ($field, $oldvalue, $newvalue, $source)
  {
    /* Handle foreign keys only as the main tab so that they are not handled twice */
    if ($this->parent->getBaseObject() !== $this) {
      return;
    }
    parent::foreignKeyUpdate($field, $oldvalue, $newvalue, $source);
  }
Côme Bernigaud's avatar
Côme Bernigaud committed
355
}