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 $acl['label_id'] = BEZ_PERMISSION_NONE; 67 $acl['participants'] = BEZ_PERMISSION_NONE; 68 69 //BEZ_AUTH_VIEWER is also token viewer 70 if ($this->level >= BEZ_AUTH_VIEWER) { 71 //user can display everything 72 $acl = array_map(function($value) { 73 return BEZ_PERMISSION_VIEW; 74 }, $acl); 75 } 76 77 if ($this->level >= BEZ_AUTH_USER) { 78 $acl['id'] = BEZ_PERMISSION_CHANGE; 79 } 80 81 if ($this->level >= BEZ_AUTH_LEADER) { 82 $acl['title'] = BEZ_PERMISSION_CHANGE; 83 $acl['content'] = BEZ_PERMISSION_CHANGE; 84 $acl['coordinator'] = BEZ_PERMISSION_CHANGE; 85 $acl['label_id'] = BEZ_PERMISSION_CHANGE; 86 $acl['private'] = BEZ_PERMISSION_CHANGE; 87 } 88 89 if ($this->level >= BEZ_AUTH_ADMIN) { 90 //user can edit everythig 91 $acl = array_map(function($value) { 92 return BEZ_PERMISSION_DELETE; 93 }, $acl); 94 } 95 96 return $acl; 97 } 98 99 100 private function check_thread(Thread $thread) { 101 $acl = $this->static_thread(); 102 103 //we create new issue 104 if ($thread->id === NULL) { 105 if ($this->level >= BEZ_AUTH_USER) { 106 $acl['title'] = BEZ_PERMISSION_CHANGE; 107 $acl['content'] = BEZ_PERMISSION_CHANGE; 108 $acl['type'] = BEZ_PERMISSION_CHANGE; 109 } 110 111 if ($this->level >= BEZ_AUTH_LEADER) { 112 $acl['coordinator'] = BEZ_PERMISSION_CHANGE; 113 $acl['label_id'] = BEZ_PERMISSION_CHANGE; 114 } 115 116 return $acl; 117 } 118 119 //private threads 120 if ($this->level < BEZ_AUTH_ADMIN && $thread->private == '1') { 121 if ($thread->get_participant($this->model->user_nick) === false) { 122 return array_fill_keys(Thread::get_columns(), BEZ_PERMISSION_NONE); 123 } 124 } 125 126 if ($this->level <= BEZ_AUTH_LEADER) { 127 $acl['title'] = BEZ_PERMISSION_VIEW; 128 $acl['content'] = BEZ_PERMISSION_VIEW; 129 $acl['coordinator'] = BEZ_PERMISSION_VIEW; 130 $acl['label_id'] = BEZ_PERMISSION_VIEW; 131 $acl['private'] = BEZ_PERMISSION_VIEW; 132 } 133 134 135 if ($thread->state == 'proposal' && 136 $thread->original_poster == $this->model->user_nick) { 137 $acl['title'] = BEZ_PERMISSION_CHANGE; 138 $acl['content'] = BEZ_PERMISSION_CHANGE; 139 } 140 141 //leader can change coordinator 142 if ($thread->state == 'proposal' && 143 $this->level >= BEZ_AUTH_LEADER) { 144 145 $acl['title'] = BEZ_PERMISSION_CHANGE; 146 $acl['content'] = BEZ_PERMISSION_CHANGE; 147 148 //coordinator can change coordinator 149 $acl['coordinator'] = BEZ_PERMISSION_CHANGE; 150 } 151 152 if ($thread->coordinator == $this->model->user_nick) { 153 $acl['title'] = BEZ_PERMISSION_CHANGE; 154 $acl['content'] = BEZ_PERMISSION_CHANGE; 155 156 //coordinator can change coordinator 157 $acl['coordinator'] = BEZ_PERMISSION_CHANGE; 158 159 $acl['state'] = BEZ_PERMISSION_CHANGE; 160 161 $acl['label_id'] = BEZ_PERMISSION_CHANGE; 162 163 $acl['private'] = BEZ_PERMISSION_CHANGE; 164 } 165 166 return $acl; 167 } 168 169 private function static_task() { 170 $acl = array_fill_keys(Task::get_columns(), BEZ_PERMISSION_NONE); 171 172 //BEZ_AUTH_VIEWER is also token viewer 173 if ($this->level >= BEZ_AUTH_VIEWER) { 174 //user can display everythig 175 $acl = array_map(function($value) { 176 return BEZ_PERMISSION_VIEW; 177 }, $acl); 178 } 179 180 //user can add tasks 181 if ($this->level >= BEZ_AUTH_USER) { 182 $acl['id'] = BEZ_PERMISSION_CHANGE; 183 } 184 185 if ($this->level >= BEZ_AUTH_ADMIN) { 186 //user can edit everythig 187 $acl = array_map(function($value) { 188 return BEZ_PERMISSION_DELETE; 189 }, $acl); 190 } 191 192 return $acl; 193 } 194 195 //if user can chante id => he can delete record 196 private function check_task($task) { 197 $acl = $this->static_task(); 198 199 //we create new task 200 if ($task->id === NULL) { 201 202 if ($task->coordinator == $this->model->user_nick || 203 ($task->thread_id == '' && $this->level >= BEZ_AUTH_LEADER)) { 204 $acl['content'] = BEZ_PERMISSION_CHANGE; 205 $acl['task_program_id'] = BEZ_PERMISSION_CHANGE; 206 $acl['assignee'] = BEZ_PERMISSION_CHANGE; 207 $acl['cost'] = BEZ_PERMISSION_CHANGE; 208 $acl['plan_date'] = BEZ_PERMISSION_CHANGE; 209 $acl['all_day_event'] = BEZ_PERMISSION_CHANGE; 210 $acl['start_time'] = BEZ_PERMISSION_CHANGE; 211 $acl['finish_time'] = BEZ_PERMISSION_CHANGE; 212 } 213 214 //no assignee 215 if ($task->thread_id == '') { 216 $acl['content'] = BEZ_PERMISSION_CHANGE; 217 $acl['task_program_id'] = BEZ_PERMISSION_CHANGE; 218 $acl['cost'] = BEZ_PERMISSION_CHANGE; 219 $acl['plan_date'] = BEZ_PERMISSION_CHANGE; 220 $acl['all_day_event'] = BEZ_PERMISSION_CHANGE; 221 $acl['start_time'] = BEZ_PERMISSION_CHANGE; 222 $acl['finish_time'] = BEZ_PERMISSION_CHANGE; 223 } 224 225 return $acl; 226 } 227 228 229 if ($task->coordinator == $this->model->user_nick || 230 ($task->thread_id == '' && $this->level >= BEZ_AUTH_LEADER)) { 231 232 //we can change cause 233 $acl['thread_comment_id'] = BEZ_PERMISSION_CHANGE; 234 235 $acl['state'] = BEZ_PERMISSION_CHANGE; 236 237 $acl['content'] = BEZ_PERMISSION_CHANGE; 238 $acl['task_program_id'] = BEZ_PERMISSION_CHANGE; 239 $acl['assignee'] = BEZ_PERMISSION_CHANGE; 240 $acl['cost'] = BEZ_PERMISSION_CHANGE; 241 242 $acl['plan_date'] = BEZ_PERMISSION_CHANGE; 243 $acl['all_day_event'] = BEZ_PERMISSION_CHANGE; 244 $acl['start_time'] = BEZ_PERMISSION_CHANGE; 245 $acl['finish_time'] = BEZ_PERMISSION_CHANGE; 246 } 247 248 if ($task->thread_id == '' && 249 $task->original_poster == $this->model->user_nick && 250 $task->assignee == $this->model->user_nick) { 251 252 253 $acl['content'] = BEZ_PERMISSION_CHANGE; 254 $acl['task_program_id'] = BEZ_PERMISSION_CHANGE; 255 //no executor 256 $acl['cost'] = BEZ_PERMISSION_CHANGE; 257 $acl['plan_date'] = BEZ_PERMISSION_CHANGE; 258 $acl['all_day_event'] = BEZ_PERMISSION_CHANGE; 259 $acl['start_time'] = BEZ_PERMISSION_CHANGE; 260 $acl['finish_time'] = BEZ_PERMISSION_CHANGE; 261 } 262 263 //user can solve his tasks 264 if ($task->assignee == $this->model->user_nick) { 265 $acl['state'] = BEZ_PERMISSION_CHANGE; 266 } 267 268 return $acl; 269 270 } 271 272 private function static_thread_comment() { 273 $acl = array_fill_keys(Thread_comment::get_columns(), BEZ_PERMISSION_NONE); 274 275 //virtual columns 276 277 //BEZ_AUTH_VIEWER is also token viewer 278 if ($this->level >= BEZ_AUTH_VIEWER) { 279 //user can display everythig 280 $acl = array_map(function($value) { 281 return BEZ_PERMISSION_VIEW; 282 }, $acl); 283 } 284 285 if ($this->level >= BEZ_AUTH_ADMIN) { 286 //user can edit everythig 287 $acl = array_map(function($value) { 288 return BEZ_PERMISSION_DELETE; 289 }, $acl); 290 } 291 292 return $acl; 293 } 294 295 private function check_thread_comment(Thread_comment $thread_comment) { 296 $acl = $this->static_thread_comment(); 297 298 //we create new commcause 299 if ($thread_comment->id === NULL) { 300 if ($this->level >= BEZ_AUTH_USER) { 301 $acl['content'] = BEZ_PERMISSION_CHANGE; 302 } 303 304 if ($thread_comment->coordinator === $this->model->user_nick) { 305 $acl['type'] = BEZ_PERMISSION_CHANGE; 306 $acl['content'] = BEZ_PERMISSION_CHANGE; 307 } 308 309 return $acl; 310 } 311 312 313 if ($thread_comment->coordinator === $this->model->user_nick) { 314 $acl['type'] = BEZ_PERMISSION_CHANGE; 315 $acl['content'] = BEZ_PERMISSION_CHANGE; 316 317 //we can only delete records when there is no tasks subscribed to issue 318 if ($thread_comment->task_count === 0) { 319 $acl['id'] = BEZ_PERMISSION_CHANGE; 320 } 321 322 } 323 324 //jeżeli ktoś zmieni typ z komentarza na przyczynę, tracimy możliwość edycji 325 if ($thread_comment->author === $this->model->user_nick && 326 $thread_comment->type == '0') { 327 $acl['content'] = BEZ_PERMISSION_CHANGE; 328 329 //we can only delete records when there is no tasks subscribed to issue 330 if ($thread_comment->task_count === 0) { 331 $acl['id'] = BEZ_PERMISSION_CHANGE; 332 } 333 } 334 335 return $acl; 336 337 } 338 339 private function static_label() { 340 $acl = array_fill_keys(Label::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_label(Label $label) { 360 return $this->static_label(); 361 } 362 363 private function static_task_program() { 364 $acl = array_fill_keys(Task_program::get_columns(), BEZ_PERMISSION_NONE); 365 366 if ($this->level >= BEZ_AUTH_USER) { 367 //user can display everythig 368 $acl = array_map(function($value) { 369 return BEZ_PERMISSION_VIEW; 370 }, $acl); 371 } 372 373 if ($this->level >= BEZ_AUTH_ADMIN) { 374 //admin can edit everythig 375 $acl = array_map(function($value) { 376 return BEZ_PERMISSION_DELETE; 377 }, $acl); 378 } 379 380 return $acl; 381 } 382 383 private function check_task_program(Task_program $task_program) { 384 return $this->static_label(); 385 } 386 387 private function static_task_comment() { 388 $acl = array_fill_keys(Task_comment::get_columns(), BEZ_PERMISSION_NONE); 389 390 //BEZ_AUTH_VIEWER is also token viewer 391 if ($this->level >= BEZ_AUTH_VIEWER) { 392 //user can display everythig 393 $acl = array_map(function($value) { 394 return BEZ_PERMISSION_VIEW; 395 }, $acl); 396 } 397 398 if ($this->level >= BEZ_AUTH_ADMIN) { 399 //user can edit everything 400 $acl = array_map(function($value) { 401 return BEZ_PERMISSION_DELETE; 402 }, $acl); 403 } 404 405 return $acl; 406 } 407 408 private function check_task_comment(Task_comment $task_comment) { 409 $acl = $this->static_task_comment(); 410 411 //we create new comment 412 if ($task_comment->id == NULL) { 413 if ($this->level >= BEZ_AUTH_USER) { 414 $acl['content'] = BEZ_PERMISSION_CHANGE; 415 } 416 417 return $acl; 418 } 419 420 421 if ($this->level >= BEZ_AUTH_LEADER) { 422 $acl['id'] = BEZ_PERMISSION_DELETE; 423 $acl['content'] = BEZ_PERMISSION_CHANGE; 424 } 425 426 427 if ($task_comment->author === $this->model->user_nick) { 428 $acl['content'] = BEZ_PERMISSION_CHANGE; 429 $acl['id'] = BEZ_PERMISSION_DELETE; 430 } 431 432 return $acl; 433 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