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