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