1<?php 2/** 3 * DokuWiki Plugin forceuserchange (Action Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Henry Pan <dokuwiki.plugin@phy25.com> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) { 11 die(); 12} 13 14class action_plugin_forceuserchange extends DokuWiki_Action_Plugin 15{ 16 const PROFILE_ACT_NAME = 'profile'; 17 18 /** 19 * Registers a callback function for a given event 20 * 21 * @param Doku_Event_Handler $controller DokuWiki's event controller object 22 * 23 * @return void 24 */ 25 public function register(Doku_Event_Handler $controller) 26 { 27 $controller->register_hook('AUTH_LOGIN_CHECK', 'AFTER', $this, 'handle_auth_login_check'); 28 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_action_act_preprocess'); 29 $controller->register_hook('ACTION_HEADERS_SEND', 'AFTER', $this, 'handle_tpl_act_render'); 30 $controller->register_hook('AUTH_USER_CHANGE', 'AFTER', $this, 'handle_auth_user_change'); 31 if (!$this->getConf('allowsamepw')){ 32 $controller->register_hook('AUTH_USER_CHANGE', 'BEFORE', $this, 'prevent_same_password'); 33 } 34 } 35 36 public function handle_auth_login_check(Doku_Event $event, $param) 37 { 38 if ($event->result == true) { 39 // logged in 40 if ($this->user_required_to_stop()) { 41 // if slient (e.g. rpc, cookie) then reject the login 42 // since we won't have a chance to redirect user to profile change 43 if ($event->data['silent']) { 44 auth_logoff(); 45 $event->result = false; 46 return; 47 } 48 } 49 } 50 } 51 52 public function handle_action_act_preprocess(Doku_Event $event, $param) 53 { 54 global $ID; 55 if ($this->user_required_to_stop()) { 56 if ($event->data != self::PROFILE_ACT_NAME) { 57 // not silent: we need to redirect user to profile page, if they are not there 58 // this is put here to prevent profile page rewriting $ACT after an attempt 59 // but user is still required to change as required 60 // when profile rewrites $ACT this will be called multiple times 61 return send_redirect(wl($ID, array('do' => self::PROFILE_ACT_NAME), true, '&')); 62 } 63 } 64 } 65 66 /** 67 * Inject message to inform user that they need to complete a change 68 */ 69 public function handle_tpl_act_render(Doku_Event $event, $param) 70 { 71 global $ACT; 72 if ($this->user_required_to_stop()) { 73 if ($ACT == self::PROFILE_ACT_NAME) { 74 msg(sprintf($this->getLang('msg_forceupdate'), $this->getConf('allowsamepw') ? $this->getLang('msg_sameallowed') : '')); 75 } 76 } 77 } 78 79 protected function get_user_groups($user = null) { 80 global $USERINFO, $auth, $INPUT; 81 $uinfo = $USERINFO; 82 if ($user && $user !== $INPUT->server->str('REMOTE_USER')) { 83 // fetch user info 84 $uinfo = $auth->getUserData($user); 85 } 86 return (array) $uinfo['grps']; 87 } 88 89 protected function user_required_to_stop($user = null) { 90 global $INPUT; 91 $grps = $this->get_user_groups($user); 92 $has_group = array_search($this->getConf('groupname'), $grps) !== false; 93 if ($this->getConf('grouprel') == 'excluding') { 94 return !empty($INPUT->server->str('REMOTE_USER')) && !$has_group; // users not having the group are required to stop 95 }else{ 96 return $has_group; 97 } 98 } 99 100 /** 101 * Change user group accordingly if user did the required change 102 */ 103 public function handle_auth_user_change(Doku_Event $event, $param) 104 { 105 global $auth; 106 if ( 107 $event->data['type'] == 'modify' && isset($event->data['params'][1]['pass']) && 108 $event->data['modification_result'] && $this->user_required_to_stop($event->data['params'][0]) 109 ) { 110 // modify group 111 $user = $event->data['params'][0]; 112 $grps = $this->get_user_groups($user); 113 $key = array_search($this->getConf('groupname'), $grps); 114 if ($this->getConf('grouprel') == 'including') { 115 if ($key !== false) { 116 array_splice($grps, $key, 1); 117 $auth->triggerUserMod('modify', array($user, array('grps'=>$grps))); 118 } 119 } else { 120 if ($key === false) { 121 $grps[] = $this->getConf('groupname'); 122 $auth->triggerUserMod('modify', array($user, array('grps'=>$grps))); 123 } 124 } 125 } 126 } 127 128 public function prevent_same_password(Doku_Event $event, $param) 129 { 130 global $auth, $INPUT; 131 if ( 132 $event->data['type'] == 'modify' && isset($event->data['params'][1]['pass']) && 133 $event->data['params'][0] == $INPUT->server->str('REMOTE_USER') && 134 $this->user_required_to_stop($event->data['params'][0]) 135 ) 136 { 137 // check password 138 $user = $event->data['params'][0]; 139 $pass = $event->data['params'][1]['pass']; 140 if (!$auth->canDo('external') && $auth->checkPass($user, $pass)){ 141 // same password 142 $event->preventDefault(); 143 msg($this->getLang('msg_errorpw'), -1); 144 } 145 } 146 } 147} 148