xref: /plugin/bez/mdl/Acl.php (revision fe5d6d1ebd253c129098b67fff8cf438a54d8650)
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 check_commcause($commcause) {
278        $acl = array(
279            'id'            => BEZ_PERMISSION_NONE,
280            'issue'         => BEZ_PERMISSION_NONE,
281            'datetime'      => BEZ_PERMISSION_NONE,
282            'reporter'      => BEZ_PERMISSION_NONE,
283            'type'          => BEZ_PERMISSION_NONE,
284            'content'       => BEZ_PERMISSION_NONE,
285            'content_cache'   => BEZ_PERMISSION_NONE
286        );
287
288        if ($this->level >= BEZ_AUTH_VIEWER) {
289            //user can display everythig
290            $acl = array_map(function($value) {
291                return BEZ_PERMISSION_VIEW;
292            }, $acl);
293        }
294
295        if ($this->level >= BEZ_AUTH_ADMIN) {
296            //admin can edit everythig
297            $acl = array_map(function($value) {
298                return BEZ_PERMISSION_CHANGE;
299            }, $acl);
300
301            return $acl;
302        }
303        //we create new commcause
304        if ($commcause->id === NULL) {
305            if ($this->level >= BEZ_USER) {
306                $acl['content'] = BEZ_PERMISSION_CHANGE;
307            }
308
309            if ($commcause->coordinator === $this->model->user_nick) {
310                $acl['type'] = BEZ_PERMISSION_CHANGE;
311                $acl['content'] = BEZ_PERMISSION_CHANGE;
312            }
313
314            return $acl;
315        }
316
317
318        if ($commcause->coordinator === $this->model->user_nick) {
319            $acl['type'] = BEZ_PERMISSION_CHANGE;
320            $acl['content'] = BEZ_PERMISSION_CHANGE;
321
322            //we can only delete records when there is no tasks subscribed to issue
323            if ($commcause->tasks_count === 0) {
324                 $acl['id'] = BEZ_PERMISSION_CHANGE;
325            }
326
327        }
328
329        //jeżeli ktoś zmieni typ z komentarza na przyczynę, tracimy możliwość edycji
330        if ($commcause->reporter === $this->model->user_nick &&
331            $commcause->type === '0') {
332            $acl['content'] = BEZ_PERMISSION_CHANGE;
333
334            //we can only delete records when there is no tasks subscribed to issue
335            if ($commcause->tasks_count === 0) {
336                 $acl['id'] = BEZ_PERMISSION_CHANGE;
337            }
338        }
339
340        return $acl;
341
342    }
343
344    private function static_label() {
345        $acl = array_fill_keys(Label::get_columns(), BEZ_PERMISSION_NONE);
346
347        if ($this->level >= BEZ_AUTH_USER) {
348            //user can display everythig
349            $acl = array_map(function($value) {
350                return BEZ_PERMISSION_VIEW;
351            }, $acl);
352        }
353
354        if ($this->level >= BEZ_AUTH_ADMIN) {
355            //admin can edit everythig
356            $acl = array_map(function($value) {
357                return BEZ_PERMISSION_CHANGE;
358            }, $acl);
359        }
360
361        return $acl;
362    }
363
364    private function check_label(Label $label) {
365        return $this->static_label();
366    }
367
368   private function check_tasktype($tasktype) {
369        $acl = array(
370            'id'            => BEZ_PERMISSION_NONE,
371            'pl'         => BEZ_PERMISSION_NONE,
372            'en'      => BEZ_PERMISSION_NONE
373        );
374
375        if ($this->level >= BEZ_AUTH_USER) {
376            //user can display everythig
377            $acl = array_map(function($value) {
378                return BEZ_PERMISSION_VIEW;
379            }, $acl);
380        }
381
382        if ($this->level >= BEZ_AUTH_ADMIN) {
383            //admin can edit everythig
384            $acl = array_map(function($value) {
385                return BEZ_PERMISSION_CHANGE;
386            }, $acl);
387        }
388
389        return $acl;
390    }
391
392    /*returns array */
393    public function check(Entity $obj) {
394        $method = 'check_'.$obj->get_table_name();
395        if (!method_exists($this, $method)) {
396            throw new \Exception('no acl rules set for table: '.$obj->get_table_name());
397        }
398        return $this->$method($obj);
399    }
400
401    public function check_field(Entity $obj, $field) {
402        $acl = $this->check($obj);
403
404        if (isset($acl[$field])) {
405            return $acl[$field];
406        }
407        return BEZ_PERMISSION_UNKNOWN;
408    }
409
410    public function check_static($table) {
411        $method = 'static_'.$table;
412        if (!method_exists($this, $method)) {
413            throw new \Exception('no acl rules set for table: '.$table);
414        }
415        return $this->$method($table);
416    }
417
418    public function check_static_field($table, $field) {
419        $acl = $this->check_static($table);
420        return $acl[$field];
421    }
422
423
424    public function can_change(Entity $obj, $field) {
425        if ($this->check_field($obj, $field) < BEZ_PERMISSION_CHANGE) {
426            $table = $obj->get_table_name();
427            $id = $obj->id;
428            throw new PermissionDeniedException('user cannot change field "'.$field.'" in table "'.$table.', rowid: "'.$id.'"');
429        }
430    }
431}
432