| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- <?php
- class userZen extends user
- {
- /**
- * 检查缓存目录和数据目录访问权限。如果不能访问,终止程序并输出提示信息。
- * Check the access permissions of the cache directory and data directory. If you cannot access, terminate the program and output the prompt message.
- *
- * @access public
- * @return void
- */
- public function checkDirPermission()
- {
- $canModifyDIR = true;
- if($this->checkTmp() === false)
- {
- $canModifyDIR = false;
- $folderPath = $this->app->tmpRoot;
- }
- elseif(!$this->checkDataRoot())
- {
- $canModifyDIR = false;
- $folderPath = $this->app->dataRoot;
- }
- if(!$canModifyDIR)
- {
- $lang = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? $this->lang->user->mkdirWin : $this->lang->user->mkdirLinux;
- $message = sprintf($lang, $folderPath, $folderPath, $folderPath, $folderPath);
- if($_POST) $this->send(array('result' => 'fail', 'message' => array('size' => 'md', 'message' => array('html' => str_replace("\n", '<br>', strip_tags($message))))));
- helper::end($message);
- }
- }
- /**
- * 判断附件目录(dataRoot)对当前 PHP 进程是否可读写。
- * Check whether the upload directory is readable and writable by the current PHP process.
- *
- * @access protected
- * @return bool
- */
- protected function checkDataRoot()
- {
- $dataRoot = $this->app->dataRoot;
- if(!is_dir($dataRoot)) return false;
- $isWin = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
- if($isWin) return is_readable($dataRoot) && is_writable($dataRoot);
- if(is_readable($dataRoot) && is_writable($dataRoot)) return true;
- $perms = @fileperms($dataRoot);
- if($perms === false) return false;
- $mode = $perms & 07777;
- $ownerId = @fileowner($dataRoot);
- if($ownerId === false) return false;
- if($ownerId === posix_geteuid()) return ($mode & 0700) === 0700;
- return ($mode & 0007) === 0007;
- }
- /**
- * 检查缓存目录是否有写权限。
- * Check if the tmp directory is writable.
- *
- * @access public
- * @return bool
- */
- public function checkTmp()
- {
- if(!is_dir($this->app->tmpRoot)) mkdir($this->app->tmpRoot, 0755, true);
- if(!is_dir($this->app->cacheRoot)) mkdir($this->app->cacheRoot, 0755, true);
- if(!is_dir($this->app->logRoot)) mkdir($this->app->logRoot, 0755, true);
- if(!is_dir($this->app->logRoot)) return false;
- $file = $this->app->logRoot . DS . 'demo.txt';
- if($fp = @fopen($file, 'a+'))
- {
- @fclose($fp);
- @unlink($file);
- return true;
- }
- return false;
- }
- /**
- * 获取一个用户用于 json 格式返回给前台。
- * Get a user for json format to return to the front end.
- *
- * @param object $user
- * @access public
- * @return object
- */
- public function getUserForJSON($user)
- {
- unset($user->password);
- unset($user->deleted);
- $user->token = session_id(); // App client will use session id as token.
- $user->company = $this->app->company->name;
- return $user;
- }
- /**
- * 获取 FeatureBar 导航。
- * Get featureBar menus.
- *
- * @param object $user
- * @access public
- * @return array
- */
- public function getFeatureBarMenus($user)
- {
- $moduleName = $this->app->moduleName;
- $methodName = $this->app->methodName;
- $storyType = zget($this->app->params, 'storyType', '');
- $params = "userID={$user->id}";
- $featureBarMenus = array();
- if(common::hasPriv($moduleName, 'todo')) $featureBarMenus['todo'] = array('active' => false, 'url' => $this->createLink($moduleName, 'view', $params), 'text' => $this->lang->user->schedule);
- if(common::hasPriv($moduleName, 'task')) $featureBarMenus['task'] = array('active' => false, 'url' => $this->createLink($moduleName, 'task', $params), 'text' => $this->lang->user->task);
- if($this->config->URAndSR && $this->config->vision == 'rnd') $featureBarMenus['requirement'] = array('active' => false, 'url' => $this->createLink($moduleName, 'story', "$params&storyType=requirement"), 'text' => $this->lang->URCommon);
- if(common::hasPriv($moduleName, 'story')) $featureBarMenus['story'] = array('active' => false, 'url' => $this->createLink($moduleName, 'story', "$params&storyType=story"), 'text' => $this->lang->SRCommon);
- if(common::hasPriv($moduleName, 'bug')) $featureBarMenus['bug'] = array('active' => false, 'url' => $this->createLink($moduleName, 'bug', $params), 'text' => $this->lang->user->bug);
- if(common::hasPriv($moduleName, 'testtask')) $featureBarMenus['testtask'] = array('active' => false, 'url' => $this->createLink($moduleName, 'testtask', $params), 'text' => $this->lang->user->testTask);
- if(common::hasPriv($moduleName, 'testcase')) $featureBarMenus['testcase'] = array('active' => false, 'url' => $this->createLink($moduleName, 'testcase', $params), 'text' => $this->lang->user->testCase);
- if(common::hasPriv($moduleName, 'execution') && in_array($this->config->systemMode, array('ALM', 'PLM'))) $featureBarMenus['execution'] = array('active' => false, 'url' => $this->createLink($moduleName, 'execution', $params), 'text' => $this->lang->user->execution);
- if(common::hasPriv($moduleName, 'issue') && in_array($this->config->edition, array('max', 'ipd')) && helper::hasFeature('issue')) $featureBarMenus['issue'] = array('active' => false, 'url' => $this->createLink($moduleName, 'issue', $params), 'text' => $this->lang->user->issue);
- if(common::hasPriv($moduleName, 'risk') && in_array($this->config->edition, array('max', 'ipd')) && helper::hasFeature('risk')) $featureBarMenus['risk'] = array('active' => false, 'url' => $this->createLink($moduleName, 'risk', $params), 'text' => $this->lang->user->risk);
- if(common::hasPriv($moduleName, 'dynamic')) $featureBarMenus['dynamic'] = array('active' => false, 'url' => $this->createLink($moduleName, 'dynamic', "$params&type=today"), 'text' => $this->lang->user->dynamic);
- if(common::hasPriv($moduleName, 'profile')) $featureBarMenus['profile'] = array('active' => false, 'url' => $this->createLink($moduleName, 'profile', $params), 'text' => $this->lang->user->profile);
- if($methodName != 'story') $featureBarMenus[$methodName]['active'] = true;
- if($methodName == 'story' && $storyType == 'story') $featureBarMenus['story']['active'] = true;
- if($methodName == 'story' && $storyType == 'requirement') $featureBarMenus['requirement']['active'] = true;
- return $featureBarMenus;
- }
- /**
- * 登录。
- * Login.
- *
- * @param string $referer
- * @param string $viewType
- * @param string $loginLink
- * @param string $denyLink
- * @param string $locateReferer
- * @param string $locateWebRoot
- * @access public
- * @return array
- */
- public function login($referer = '', $viewType = '', $loginLink = '', $denyLink = '', $locateReferer = '', $locateWebRoot = '')
- {
- if(empty($_POST) && (!isset($_GET['account']) || !isset($_GET['password']))) return array();
- /* 预处理账号和密码。*/
- /* Preprocess account and password. */
- $account = '';
- $password = '';
- if($this->post->account) $account = trim($this->post->account);
- if($this->post->password) $password = trim($this->post->password);
- if($this->get->account) $account = trim($this->get->account);
- if($this->get->password) $password = trim($this->get->password);
- if(!$account) return $this->responseForLoginFail($viewType);
- /* 如果用户被锁定返回相关信息。*/
- /* Return related information if the user is locked. */
- if($this->user->checkLocked($account)) return $this->responseForLocked($viewType);
- /* 如果开启了登录验证码检查验证码是否正确。*/
- /* Check if the login captcha is correct if the login captcha is enabled. */
- if((!empty($this->config->safe->loginCaptcha) && strtolower($this->post->captcha) != strtolower($this->session->captcha) && $viewType != 'json')) return array('result' => 'fail', 'message' => $this->lang->user->errorCaptcha);
- /* 验证账号和密码。*/
- /* Verify account and password. */
- $passwordStrength = $viewType == 'json' ? 1 : (int)$this->post->passwordStrength;
- $user = $this->user->identify($account, $password, $passwordStrength);
- /* 登录失败返回错误信息。*/
- /* Return error message if login failed. */
- if(!$user) return $this->responseForLoginfail($viewType, $account);
- /* 获取用户所属权限组、权限和视图,记录日志并发放登录积分。*/
- /* Get user's group, priv and view, save log and give login score. */
- helper::setcookie('logout', false, 0);
- $user = $this->user->login($user, true, $this->post->keepLogin);
- /* 以 json 格式返回用户数据。*/
- /* Return user data in json format. */
- if($viewType == 'json') return array('status' => 'success', 'token' => session_id(), 'user' => $this->getUserForJSON($user));
- /* 来源网址不满足条件时跳转到首页。*/
- /* Jump to home page if the referer does not meet the conditions. */
- if(!$referer || strpos($referer, $loginLink) !== false || strpos($referer, $denyLink) !== false || strpos($referer, 'ajax') !== false || strpos($referer, 'block') !== false) return array('result' => 'success', 'locate' => $locateWebRoot);
- /* 解析来源网址包含的模块和方法。*/
- /* Parse the module and method contained in the referer. */
- list($module, $method) = $this->parseLoginModuleAndMethod($referer);
- /* 如果模块和方法为空或者不合法则跳转到首页。*/
- /* Jump to home page if the module and method are empty or illegal. */
- if(empty($module) || empty($method) || !$this->app->checkModuleName($module, false) || !$this->app->checkMethodName($module, false)) return array('result' => 'success', 'locate' => $locateWebRoot);
- /* 如果有模块和方法的访问权限则跳转到来源网址。*/
- /* Jump to the referer if there is access to the module and method. */
- if(common::hasPriv($module, $method)) return array('result' => 'success', 'locate' => $locateReferer);
- /* 跳转到首页。*/
- /* Jump to home page. */
- return array('result' => 'success', 'locate' => $locateWebRoot);
- }
- /**
- * 解析来源网址包含的模块和方法。
- * Parse the module and method contained in the referer.
- *
- * @param string $referer
- * @access public
- * @return array
- */
- public function parseLoginModuleAndMethod($referer)
- {
- $module = '';
- $method = '';
- /* Get the module and method of the referer. */
- if($this->config->requestType == 'PATH_INFO')
- {
- $requestFix = $this->config->requestFix;
- $path = substr($referer, strrpos($referer, '/') + 1);
- $path = rtrim($path, '.html');
- if($path && strpos($path, $requestFix) !== false) list($module, $method) = explode($requestFix, $path);
- }
- else
- {
- $url = html_entity_decode($referer);
- $param = substr($url, strrpos($url, '?') + 1);
- if(strpos($param, '&') !== false) list($module, $method) = explode('&', $param);
- $module = str_replace('m=', '', $module);
- $method = str_replace('f=', '', $method);
- }
- return array($module, $method);
- }
- /**
- * 构建职位和权限组数据。
- * Prepare roles and groups data.
- *
- * @access public
- * @return void
- */
- public function prepareRolesAndGroups()
- {
- $groupList = array();
- $roleGroup = array();
- $groups = $this->dao->select('id, name, role, vision')->from(TABLE_GROUP)->where('vision')->eq($this->config->vision)->andWhere('project')->eq('0')->fetchAll();
- foreach($groups as $group)
- {
- $groupList[$group->id] = $group->name;
- if($group->role) $roleGroup[$group->role] = $group->id;
- }
- $this->view->groupList = $groupList;
- $this->view->roleGroup = $roleGroup;
- }
- /**
- * 构建自定义字段。
- * Prepare custom fields.
- *
- * @param string $method
- * @param string $requiredMethod
- * @access public
- * @return void
- */
- public function prepareCustomFields($method, $requiredMethod)
- {
- $customFields = 'custom' . ucfirst($method) . 'Fields';
- $showField = $method . 'Fields';
- /* 获取所有的联系方式字段。*/
- /* Get all contact fields. */
- $allContactFields = array_keys($this->lang->user->contactFieldList);
- /* 获取自定义的联系方式字段,转为数组并去空、去重。*/
- /* Get custom contact fields, convert to array and remove empty and duplicate. */
- $customContactFields = array_unique(array_filter(explode(',', trim($this->config->user->contactField, ','))));
- /* 获取不可用的联系方式字段。*/
- /* Get unavailable contact fields. */
- $unAvailableContactFields = array_diff($allContactFields, $customContactFields);
- /* 从配置文件获取所有自定义字段,转为数组并去空、去重。*/
- /* Get all custom fields from config file, convert to array and remove empty and duplicate. */
- $customFields = array_unique(array_filter(explode(',', trim($this->config->user->list->$customFields, ','))));
- /* 从自定义字段中去除不可用的联系方式字段。*/
- /* Remove unavailable contact fields from custom fields. */
- $customFields = array_diff($customFields, $unAvailableContactFields);
- /* 获取可以显示的字段。*/
- /* Get fields that can be displayed. */
- $listFields = array();
- foreach($customFields as $field) $listFields[$field] = $this->lang->user->$field;
- /* 从配置文件获取必填项字段,转为数组并去空、去重。*/
- /* Get required fields from config file, convert to array and remove empty and duplicate. */
- $requiredFields = array_unique(array_filter(explode(',', trim($this->config->user->$requiredMethod->requiredFields, ','))));
- /* 从数据库中获取应该显示的字段。*/
- /* Get fields that should be displayed from database. */
- $showFields = $this->loadModel('setting')->getItem("owner={$this->app->user->account}&module=user§ion=custom&key={$showField}");
- /* 从配置文件中获取应该显示的字段。*/
- /* Get fields that should be displayed from config file. */
- if(!$showFields) $showFields = $this->config->user->custom->$showField;
- /* 把应该显示的字段转为数组并去空、去重。*/
- /* Convert fields that should be displayed to array and remove empty and duplicate. */
- $showFields = array_unique(array_filter(explode(',', trim($showFields, ','))));
- /* 把应该显示的字段和必填项字段合并,确保自定义字段面板中必填项字段是被勾选中的。*/
- /* Merge fields that should be displayed and required fields to ensure that required fields are checked in the custom field panel. */
- $showFields = array_merge($showFields, $requiredFields);
- /* 把应该显示的字段和可用字段取交集。*/
- /* Get the intersection of fields that should be displayed and available fields. */
- $showFields = array_intersect($showFields, $customFields);
- $this->view->listFields = $listFields;
- $this->view->showFields = $showFields;
- }
- /**
- * 重新加载语言项。
- * Reload language items.
- *
- * @param string $lang
- * @access public
- * @return void
- */
- public function reloadLang($lang)
- {
- $this->app->setClientLang($lang);
- $this->app->loadLang('user');
- }
- /**
- * 用户已登录时的响应。
- * Response when user has logged in.
- *
- * @param string $referer
- * @param string $viewType
- * @param string $loginLink
- * @param string $denyLink
- * @param string $locateReferer
- * @param string $locateWebRoot
- * @access public
- * @return array
- */
- public function responseForLogon($referer, $viewType, $loginLink, $denyLink, $locateReferer, $locateWebRoot)
- {
- helper::setcookie('logout', false, 0);
- /* 以 json 格式返回用户数据。*/
- /* Return user data in json format. */
- if($viewType == 'json') return array('status' => 'success', 'token' => session_id(), 'user' => $this->getUserForJSON($this->app->user));
- /* 来源网址不满足条件时跳转到首页。*/
- /* Jump to home page if the referer does not meet the conditions. */
- if(!$referer || strpos($referer, $loginLink) !== false || strpos($referer, $denyLink) !== false || strpos($referer, 'ajax') !== false || strpos($referer, 'block') !== false) return array('result' => 'success', 'locate' => $locateWebRoot);
- /* 跳转到来源网址。*/
- /* Jump to the referer. */
- return array('result' => 'success', 'locate' => $locateReferer);
- }
- /**
- * 用户被锁定时的响应。
- * Response when user is locked.
- *
- * @param string $viewType
- * @access public
- * @return array
- */
- public function responseForLocked($viewType)
- {
- $message = sprintf($this->lang->user->loginLocked, $this->config->user->lockMinutes);
- if($viewType == 'json') return array('status' => 'failed', 'reason' => $message);
- return array('result' => 'fail', 'message' => $message);
- }
- /**
- * 登录失败时的响应。
- * Response when login failed.
- *
- * @param string $viewType
- * @param string $account
- * @access public
- * @return array
- */
- public function responseForLoginFail($viewType, $account = '')
- {
- if($viewType == 'json') return array('status' => 'failed', 'reason' => $this->lang->user->loginFailed);
- if($account)
- {
- $remainTimes = $this->config->user->failTimes - $this->user->failPlus($account);
- if($remainTimes <= 0) return array('result' => 'fail', 'message' => sprintf($this->lang->user->loginLocked, $this->config->user->lockMinutes));
- if($remainTimes <= 3) return array('result' => 'fail', 'message' => sprintf($this->lang->user->lockWarning, $remainTimes));
- if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError());
- }
- return array('result' => 'fail', 'message' => $this->lang->user->loginFailed);
- }
- /**
- * 设置来源地址。
- * Set referer.
- *
- * @param string $referer
- * @access public
- * @return string
- */
- public function setReferer($referer = '')
- {
- $this->referer = $this->server->http_referer ? $this->server->http_referer: '';
- if(!empty($referer)) $this->referer = helper::safe64Decode($referer);
- if($this->post->referer) $this->referer = $this->post->referer;
- /* 构建禅道链接的正则表达式。*/
- /* Build zentao link regular expression. */
- $webRoot = $this->config->webRoot;
- $linkReg = $webRoot . 'index.php?' . $this->config->moduleVar . '=\w+&' . $this->config->methodVar . '=\w+';
- if($this->config->requestType == 'PATH_INFO') $linkReg = $webRoot . '\w+' . $this->config->requestFix . '\w+';
- $linkReg = str_replace(array('/', '.', '?', '-'), array('\/', '\.', '\?', '\-'), $linkReg);
- /* 检查来源地址是否为禅道链接。*/
- /* Check zentao link by regular expression. */
- return preg_match('/^' . $linkReg . '/', $this->referer) ? $this->referer : $webRoot;
- }
- }
|