xref: /plugin/bez/mdl/Acl.php (revision 7fbf4c3966fc9b63e77e3ef6f091279dbce0d34f)
1<?php
2
3//if(!defined('DOKU_INC')) die('meh.');
4//
5//include_once DOKU_PLUGIN."bez/models/tokens.php";
6
7namespace dokuwiki\plugin\bez\mdl;
8
9//ACL level defines
10use dokuwiki\plugin\bez\meta\PermissionDeniedException;
11
12define('BEZ_AUTH_NONE', 0);
13define('BEZ_AUTH_VIEWER', 2);
14define('BEZ_AUTH_USER', 5);
15define('BEZ_AUTH_LEADER', 10);
16define('BEZ_AUTH_ADMIN', 20);
17
18define('BEZ_PERMISSION_UNKNOWN', -1);
19define('BEZ_PERMISSION_NONE', 0);
20define('BEZ_PERMISSION_VIEW', 1);
21define('BEZ_PERMISSION_CHANGE', 2);
22
23class Acl {
24    /** @var  Model */
25    private $model;
26
27    private $level = BEZ_AUTH_NONE;
28
29//    private $threads = array();
30//    private $commcauses = array();
31//    private $tasks = array();
32
33    private function update_level($level) {
34		if ($level > $this->level) {
35			$this->level = $level;
36		}
37	}
38
39    public function get_level() {
40        return $this->level;
41    }
42
43    public function __construct(Model $model) {
44        $this->model = $model;
45
46		$userd = $this->model->dw_auth->getUserData($this->model->user_nick);
47		if ($userd !== false && is_array($userd['grps'])) {
48			$grps = $userd['grps'];
49			if (in_array('admin', $grps ) || in_array('bez_admin', $grps )) {
50				$this->update_level(BEZ_AUTH_ADMIN);
51            } elseif (in_array('bez_leader', $grps )) {
52                $this->update_level(BEZ_AUTH_LEADER);
53			} else {
54				$this->update_level(BEZ_AUTH_USER);
55			}
56        } elseif (isset($_GET['t'])) {
57//            $page_id = $this->model->action->page_id();
58//            $toko = new Tokens();
59//
60//            if ($toko->check(trim($_GET['t']), $page_id)) {
61//                $this->update_level(BEZ_AUTH_VIEWER);
62//            }
63        }
64    }
65
66    private function static_thread() {
67        $acl = array_fill_keys(Thread::get_columns(), BEZ_PERMISSION_NONE);
68
69        //virtual columns
70        $acl['participants'] = BEZ_PERMISSION_NONE;
71        $acl['labels'] = BEZ_PERMISSION_NONE;
72
73        //BEZ_AUTH_VIEWER is also token viewer
74        if ($this->level >= BEZ_AUTH_VIEWER) {
75            //user can display everythig
76            $acl = array_map(function($value) {
77                return BEZ_PERMISSION_VIEW;
78            }, $acl);
79        }
80
81        if ($this->level >= BEZ_AUTH_ADMIN) {
82            //user can edit everythig
83            $acl = array_map(function($value) {
84                return BEZ_PERMISSION_CHANGE;
85            }, $acl);
86
87            return $acl;
88        }
89    }
90
91
92    private function check_thread(Thread $thread) {
93//        $acl = array(
94//                'id'            => BEZ_PERMISSION_NONE,
95//                'title'         => BEZ_PERMISSION_NONE,
96//                'description'   => BEZ_PERMISSION_NONE,
97//                'state'         => BEZ_PERMISSION_NONE,
98//                'opinion'       => BEZ_PERMISSION_NONE,
99//                'type'          => BEZ_PERMISSION_NONE,
100//                'coordinator'   => BEZ_PERMISSION_NONE,
101//                'reporter'      => BEZ_PERMISSION_NONE,
102//                'date'          => BEZ_PERMISSION_NONE,
103//                'last_mod'      => BEZ_PERMISSION_NONE,
104//                'last_activity' => BEZ_PERMISSION_NONE,
105//                'participants'  => BEZ_PERMISSION_NONE,
106//                'subscribents'  => BEZ_PERMISSION_NONE,
107//                'description_cache' => BEZ_PERMISSION_NONE,
108//                'opinion_cache' => BEZ_PERMISSION_NONE
109//        );
110
111        $acl = $this->static_thread();
112
113        //we create new issue
114        if ($thread->id === NULL) {
115            if ($this->level >= BEZ_AUTH_USER) {
116                $acl['title'] = BEZ_PERMISSION_CHANGE;
117                $acl['content'] = BEZ_PERMISSION_CHANGE;
118                //$acl['type'] = BEZ_PERMISSION_CHANGE;
119            }
120
121            if ($this->level >= BEZ_AUTH_LEADER) {
122                $acl['coordinator'] = BEZ_PERMISSION_CHANGE;
123            }
124
125            return $acl;
126        }
127
128        if ($thread->state === 'proposal' &&
129            $thread->original_poster === $this->model->user_nick) {
130            $acl['title'] = BEZ_PERMISSION_CHANGE;
131            $acl['content'] = BEZ_PERMISSION_CHANGE;
132            //$acl['type'] = BEZ_PERMISSION_CHANGE;
133        }
134
135        if ($thread->coordinator === $this->model->user_nick) {
136            $acl['title'] = BEZ_PERMISSION_CHANGE;
137            $acl['content'] = BEZ_PERMISSION_CHANGE;
138            //$acl['type'] = BEZ_PERMISSION_CHANGE;
139
140            //coordinator can change coordinator
141            $acl['coordinator'] = BEZ_PERMISSION_CHANGE;
142
143            $acl['state'] = BEZ_PERMISSION_CHANGE;
144            //$acl['opinion'] = BEZ_PERMISSION_CHANGE;
145        }
146
147        return $acl;
148    }
149
150    //if user can chante id => he can delete record
151    private function check_task($task) {
152        $acl = array(
153                'id'             => BEZ_PERMISSION_NONE,
154                'task'           => BEZ_PERMISSION_NONE,
155                'state'          => BEZ_PERMISSION_NONE,
156                'tasktype'       => BEZ_PERMISSION_NONE,
157                'executor'       => BEZ_PERMISSION_NONE,
158                'cost'           => BEZ_PERMISSION_NONE,
159                'reason'         => BEZ_PERMISSION_NONE,
160                'reporter'       => BEZ_PERMISSION_NONE,
161                'date'           => BEZ_PERMISSION_NONE,
162                'close_date'     => BEZ_PERMISSION_NONE,
163                'cause'          => BEZ_PERMISSION_NONE,
164                'plan_date'      => BEZ_PERMISSION_NONE,
165                'all_day_event'  => BEZ_PERMISSION_NONE,
166                'start_time'     => BEZ_PERMISSION_NONE,
167                'finish_time'    => BEZ_PERMISSION_NONE,
168                'issue'          => BEZ_PERMISSION_NONE,
169                'task_cache'     => BEZ_PERMISSION_NONE,
170                'reason_cache'   => BEZ_PERMISSION_NONE,
171                'subscribents'   => BEZ_PERMISSION_NONE
172        );
173
174        if ($this->level >= BEZ_AUTH_VIEWER) {
175            //user can display everythig
176            $acl = array_map(function($value) {
177                return BEZ_PERMISSION_VIEW;
178            }, $acl);
179        }
180
181        if ($this->level >= BEZ_AUTH_ADMIN) {
182            //admin can edit everythig
183            $acl = array_map(function($value) {
184                return BEZ_PERMISSION_CHANGE;
185            }, $acl);
186
187            return $acl;
188        }
189
190        //we create new task
191        if ($task->id === NULL) {
192
193            if ($task->coordinator === $this->model->user_nick ||
194               ($task->issue === '' && $this->level >= BEZ_AUTH_LEADER)) {
195                $acl['task'] = BEZ_PERMISSION_CHANGE;
196                $acl['tasktype'] = BEZ_PERMISSION_CHANGE;
197                $acl['executor'] = BEZ_PERMISSION_CHANGE;
198                $acl['cost'] = BEZ_PERMISSION_CHANGE;
199                $acl['plan_date'] = BEZ_PERMISSION_CHANGE;
200                $acl['all_day_event'] = BEZ_PERMISSION_CHANGE;
201                $acl['start_time'] = BEZ_PERMISSION_CHANGE;
202                $acl['finish_time'] = BEZ_PERMISSION_CHANGE;
203            }
204
205            //przypisujemy zadanie programowe samemu sobie
206            //no executor
207            if ($task->issue === '') {
208                $acl['task'] = BEZ_PERMISSION_CHANGE;
209                $acl['tasktype'] = BEZ_PERMISSION_CHANGE;
210                $acl['cost'] = BEZ_PERMISSION_CHANGE;
211                $acl['plan_date'] = BEZ_PERMISSION_CHANGE;
212                $acl['all_day_event'] = BEZ_PERMISSION_CHANGE;
213                $acl['start_time'] = BEZ_PERMISSION_CHANGE;
214                $acl['finish_time'] = BEZ_PERMISSION_CHANGE;
215            }
216
217            return $acl;
218        }
219
220        //user can change state
221        if ($task->executor === $this->model->user_nick) {
222            $acl['reason'] = BEZ_PERMISSION_CHANGE;
223            $acl['state'] = BEZ_PERMISSION_CHANGE;
224        }
225
226        //reporters can add subscribents to programme task
227        if ($task->reporter === $this->model->user_nick) {
228            $acl['subscribents'] = BEZ_PERMISSION_CHANGE;
229        }
230
231        if ($task->coordinator === $this->model->user_nick ||
232            ($task->issue === '' && $this->level >= BEZ_AUTH_LEADER)) {
233
234            $acl['reason'] = BEZ_PERMISSION_CHANGE;
235            $acl['state'] = BEZ_PERMISSION_CHANGE;
236
237            //we can chante cause
238            $acl['cause'] =  BEZ_PERMISSION_CHANGE;
239
240            $acl['task'] = BEZ_PERMISSION_CHANGE;
241            $acl['tasktype'] = BEZ_PERMISSION_CHANGE;
242            $acl['executor'] = BEZ_PERMISSION_CHANGE;
243            $acl['cost'] = BEZ_PERMISSION_CHANGE;
244            $acl['reason'] = BEZ_PERMISSION_CHANGE;
245            $acl['plan_date'] = BEZ_PERMISSION_CHANGE;
246            $acl['all_day_event'] = BEZ_PERMISSION_CHANGE;
247            $acl['start_time'] = BEZ_PERMISSION_CHANGE;
248            $acl['finish_time'] = BEZ_PERMISSION_CHANGE;
249
250
251            //leaders can add subscribents to programme tasks
252            $acl['subscribents'] = BEZ_PERMISSION_CHANGE;
253        }
254
255        if ($task->issue === '' &&
256            $task->reporter === $this->model->user_nick &&
257            $task->executor === $this->model->user_nick) {
258            $acl['reason'] = BEZ_PERMISSION_CHANGE;
259            $acl['state'] = BEZ_PERMISSION_CHANGE;
260
261            $acl['task'] = BEZ_PERMISSION_CHANGE;
262            $acl['tasktype'] = BEZ_PERMISSION_CHANGE;
263            //no executor
264            $acl['cost'] = BEZ_PERMISSION_CHANGE;
265            $acl['reason'] = BEZ_PERMISSION_CHANGE;
266            $acl['plan_date'] = BEZ_PERMISSION_CHANGE;
267            $acl['all_day_event'] = BEZ_PERMISSION_CHANGE;
268            $acl['start_time'] = BEZ_PERMISSION_CHANGE;
269            $acl['finish_time'] = BEZ_PERMISSION_CHANGE;
270        }
271
272
273        return $acl;
274
275    }
276
277    private function static_thread_comment() {
278        $acl = array_fill_keys(Thread_comment::get_columns(), BEZ_PERMISSION_NONE);
279
280        //virtual columns
281
282        //BEZ_AUTH_VIEWER is also token viewer
283        if ($this->level >= BEZ_AUTH_VIEWER) {
284            //user can display everythig
285            $acl = array_map(function($value) {
286                return BEZ_PERMISSION_VIEW;
287            }, $acl);
288        }
289
290        if ($this->level >= BEZ_AUTH_ADMIN) {
291            //user can edit everythig
292            $acl = array_map(function($value) {
293                return BEZ_PERMISSION_CHANGE;
294            }, $acl);
295
296            return $acl;
297        }
298    }
299
300    private function check_commcause($commcause) {
301        $acl = array(
302            'id'            => BEZ_PERMISSION_NONE,
303            'issue'         => BEZ_PERMISSION_NONE,
304            'datetime'      => BEZ_PERMISSION_NONE,
305            'reporter'      => BEZ_PERMISSION_NONE,
306            'type'          => BEZ_PERMISSION_NONE,
307            'content'       => BEZ_PERMISSION_NONE,
308            'content_cache'   => BEZ_PERMISSION_NONE
309        );
310
311        if ($this->level >= BEZ_AUTH_VIEWER) {
312            //user can display everythig
313            $acl = array_map(function($value) {
314                return BEZ_PERMISSION_VIEW;
315            }, $acl);
316        }
317
318        if ($this->level >= BEZ_AUTH_ADMIN) {
319            //admin can edit everythig
320            $acl = array_map(function($value) {
321                return BEZ_PERMISSION_CHANGE;
322            }, $acl);
323
324            return $acl;
325        }
326        //we create new commcause
327        if ($commcause->id === NULL) {
328            if ($this->level >= BEZ_USER) {
329                $acl['content'] = BEZ_PERMISSION_CHANGE;
330            }
331
332            if ($commcause->coordinator === $this->model->user_nick) {
333                $acl['type'] = BEZ_PERMISSION_CHANGE;
334                $acl['content'] = BEZ_PERMISSION_CHANGE;
335            }
336
337            return $acl;
338        }
339
340
341        if ($commcause->coordinator === $this->model->user_nick) {
342            $acl['type'] = BEZ_PERMISSION_CHANGE;
343            $acl['content'] = BEZ_PERMISSION_CHANGE;
344
345            //we can only delete records when there is no tasks subscribed to issue
346            if ($commcause->tasks_count === 0) {
347                 $acl['id'] = BEZ_PERMISSION_CHANGE;
348            }
349
350        }
351
352        //jeżeli ktoś zmieni typ z komentarza na przyczynę, tracimy możliwość edycji
353        if ($commcause->reporter === $this->model->user_nick &&
354            $commcause->type === '0') {
355            $acl['content'] = BEZ_PERMISSION_CHANGE;
356
357            //we can only delete records when there is no tasks subscribed to issue
358            if ($commcause->tasks_count === 0) {
359                 $acl['id'] = BEZ_PERMISSION_CHANGE;
360            }
361        }
362
363        return $acl;
364
365    }
366
367    private function static_label() {
368        $acl = array_fill_keys(Label::get_columns(), BEZ_PERMISSION_NONE);
369
370        if ($this->level >= BEZ_AUTH_USER) {
371            //user can display everythig
372            $acl = array_map(function($value) {
373                return BEZ_PERMISSION_VIEW;
374            }, $acl);
375        }
376
377        if ($this->level >= BEZ_AUTH_ADMIN) {
378            //admin can edit everythig
379            $acl = array_map(function($value) {
380                return BEZ_PERMISSION_CHANGE;
381            }, $acl);
382        }
383
384        return $acl;
385    }
386
387    private function check_label(Label $label) {
388        return $this->static_label();
389    }
390
391   private function check_tasktype($tasktype) {
392        $acl = array(
393            'id'            => BEZ_PERMISSION_NONE,
394            'pl'         => BEZ_PERMISSION_NONE,
395            'en'      => BEZ_PERMISSION_NONE
396        );
397
398        if ($this->level >= BEZ_AUTH_USER) {
399            //user can display everythig
400            $acl = array_map(function($value) {
401                return BEZ_PERMISSION_VIEW;
402            }, $acl);
403        }
404
405        if ($this->level >= BEZ_AUTH_ADMIN) {
406            //admin can edit everythig
407            $acl = array_map(function($value) {
408                return BEZ_PERMISSION_CHANGE;
409            }, $acl);
410        }
411
412        return $acl;
413    }
414
415    /*returns array */
416    public function check(Entity $obj) {
417        $method = 'check_'.$obj->get_table_name();
418        if (!method_exists($this, $method)) {
419            throw new \Exception('no acl rules set for table: '.$obj->get_table_name());
420        }
421        return $this->$method($obj);
422    }
423
424    public function check_field(Entity $obj, $field) {
425        $acl = $this->check($obj);
426
427        if (isset($acl[$field])) {
428            return $acl[$field];
429        }
430        return BEZ_PERMISSION_UNKNOWN;
431    }
432
433    public function check_static($table) {
434        $method = 'static_'.$table;
435        if (!method_exists($this, $method)) {
436            throw new \Exception('no acl rules set for table: '.$table);
437        }
438        return $this->$method($table);
439    }
440
441    public function check_static_field($table, $field) {
442        $acl = $this->check_static($table);
443        return $acl[$field];
444    }
445
446
447    public function can_change(Entity $obj, $field) {
448        if ($this->check_field($obj, $field) < BEZ_PERMISSION_CHANGE) {
449            $table = $obj->get_table_name();
450            $id = $obj->id;
451            throw new PermissionDeniedException('user cannot change field "'.$field.'" in table "'.$table.', rowid: "'.$id.'"');
452        }
453    }
454}
455