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