diff --git a/api/v2.php b/api/v2.php index 3c28567..6d9a1ea 100644 --- a/api/v2.php +++ b/api/v2.php @@ -54,6 +54,8 @@ try { } ob_clean(); + header('Content-Type: application/json; charset=utf-8'); + $apiMethod=fox\common::clearInput($request->method,"A-Z"); $apiFunction=fox\common::clearInput($request->function,"a-zA-Z0-9"); $apiXFunction=empty($request->parameters[0])?NULL:fox\common::clearInput($request->parameters[0],"a-zA-Z0-9"); @@ -78,6 +80,7 @@ try { } catch (fox\foxRequestResult $e) { ob_clean(); + header('Content-Type: application/json; charset=utf-8'); header('HTTP/1.0 '.$e->getCode().' '.$e->getMessage(), true, $e->getCode()); if ($e->retVal===null) { print json_encode(["status"=>$e->getMessage()]); diff --git a/core/fox/UUID.php b/core/fox/UUID.php new file mode 100644 index 0000000..0834b5a --- /dev/null +++ b/core/fox/UUID.php @@ -0,0 +1,115 @@ +__settings = $settings; if (empty($this::$baseSqlSelectTemplate) && ! empty($this::$sqlTable)) { - $this->__sqlSelectTemplate = "select * from `" . $this::$sqlTable . "` as `i`"; + $this->__sqlSelectTemplate = "select `i`.* from `" . $this::$sqlTable . "` as `i`"; } else { $this->__sqlSelectTemplate = $this::$baseSqlSelectTemplate; } @@ -589,10 +589,11 @@ class baseClass extends dbStoredBase implements \JsonSerializable, jsonImportabl } $xRes=static::xSearch($where, $pattern, $options, $sql); - $where = $xRes["where"]; - $join=$xRes["join"]; + $where = array_key_exists("where",$xRes)?$xRes["where"]:""; + $join=array_key_exists("join",$xRes)?$xRes["join"]:""; + $groupBy=array_key_exists("group",$xRes)?$xRes["group"]:""; - $sqlQueryString=$ref->sqlSelectTemplate.(empty($join)?"":" ".$join).(empty($where)?"":" WHERE ".$where).(empty($limit)?"":" ".$limit); + $sqlQueryString=$ref->sqlSelectTemplate.(empty($join)?"":" ".$join).(empty($where)?"":" WHERE ".$where).(empty($groupBy)?"":" GROUP BY ".$groupBy).(empty($limit)?"":" ".$limit); $res=$sql->quickExec($sqlQueryString); $rv=new searchResult(); diff --git a/core/fox/common.php b/core/fox/common.php index 075a52c..baaec4a 100644 --- a/core/fox/common.php +++ b/core/fox/common.php @@ -90,11 +90,7 @@ class common static function getGUIDc() { - mt_srand((double) microtime() * 10000); // optional for php 4.2.0 and up. - $charid = strtoupper(md5(uniqid(rand(), true))); - $hyphen = chr(45); // "-" - return substr($charid, 0, 8) . $hyphen . substr($charid, 8, 4) . $hyphen . substr($charid, 12, 4) . $hyphen . substr($charid, 16, 4) . $hyphen . substr($charid, 20, 12); - + return strtoupper(UUID::v4()); } static function getGUID() diff --git a/core/fox/modules.php b/core/fox/modules.php index 60e7585..dfbeeb3 100644 --- a/core/fox/modules.php +++ b/core/fox/modules.php @@ -43,6 +43,10 @@ class modules implements externalCallable "adminAuthMethods"=>"Manage auth methods", "viewCompanies"=>"View companies", "adminCompanies"=>"Manage companies", + "viewAllGroups"=>"Search in all groups and lists", + "viewAllLists"=>"Search in all lists", + "viewAllUsers"=>"Search in all users", + "viewOwnListsUsers"=>"Search users only from own lists" ], "configKeys"=> [ "converterURL"=>"FoxConverter URL prefix", diff --git a/core/fox/request.php b/core/fox/request.php index 9d2c0f3..c9a1ed1 100644 --- a/core/fox/request.php +++ b/core/fox/request.php @@ -180,6 +180,27 @@ class request extends baseClass implements noSqlMigration throw new foxException("Forbidden", 403); } } + + public function checkAccess(string $rule, string $modInstance=null) { + if ($modInstance==null) { $modInstance=$this->instance; } + return $this->user->checkAccess($rule, $modInstance); + } + + public function getRequestBodyItem($key) { + if ($this->requestBody!=null && property_exists($this->requestBody, $key)) { + return $this->requestBody->{$key}; + } else { + return null; + } + } + + public function getParamItem($key) { + if ($this->parameters !=null && array_key_exists($key, $this->parameters)) { + return $this->parameters[$key]; + } else { + return null; + } + } } ?> \ No newline at end of file diff --git a/core/fox/user.php b/core/fox/user.php index 5a841c0..b54c6ef 100644 --- a/core/fox/user.php +++ b/core/fox/user.php @@ -284,6 +284,22 @@ class user extends baseClass implements externalCallable $rv["config"]=(object)$this->config; return $rv; } + /** + * @param array $options - ["groups" - array of userGroup, if set - search will performed only in it] + */ + protected static function xSearch($where, $pattern, ?array $options, sql $sql) { + $ruleJoin=null; + + if ($options["groups"]) { + $groups=""; + foreach ($options["groups"] as $group) { + $groups .= (empty($groups)?"":",")."\"".$group->id."\""; + } + $ruleJoin = " INNER JOIN `tblUserGroupLink` as `l` on `l`.`userId`=`i`.`id` AND `l`.`groupId` in ($groups)"; + } + + return ["where"=>$where, "join"=>$ruleJoin, "group"=>"`i`.`id`"]; + } ### REST API public static function API_GET_list(request $request) @@ -295,6 +311,28 @@ class user extends baseClass implements externalCallable } public static function API_POST_search(request $request) { + + $opts=[]; + if ($request->checkAccess("viewAllUsers") || $request->checkAccess("adminUsers")) { + $opts=[]; + } else if ($request->checkAccess("viewOwnListsUsers")) { + $opts = [ + "groups"=>userGroup::getForUser($request->user,true), + ]; + } else { + $rv=new searchResult(); + $rv->push($request->user); + return $rv; + + } + + return static::search( + $request->getRequestBodyItem("pattern"), + $request->getRequestBodyItem("pageSize"), + $request->getRequestBodyItem("page"), + $opts + ); + if (! $request->user->checkAccess("adminUsers", "core")) { throw new foxException("Forbidden", 403); } diff --git a/core/fox/userGroup.php b/core/fox/userGroup.php index ff9d3e1..c35bfc4 100644 --- a/core/fox/userGroup.php +++ b/core/fox/userGroup.php @@ -40,7 +40,8 @@ class userGroup extends baseClass implements externalCallable public static $sqlColumns = [ "name" => [ "type" => "VARCHAR(255)", - "index" => "INDEX" + "index" => "INDEX", + "search"=>"LIKE", ], "companyId" => [ "type" => "INT", @@ -87,22 +88,18 @@ class userGroup extends baseClass implements externalCallable * */ protected static function xSearch($where, $pattern, ?array $options, sql $sql) { - $accessRule=(empty($options["accessRule"])?null:$options["accessRule"]); $isList=(array_key_exists("isList", $options)?$options["isList"]:false); $ruleJoin=null; - $ruleWhere=null; - + if ($isList !== false) { - $ruleWhere .= " and `i`.`isList` = " . ($isList == true ? 1 : 0); + $where = (empty($where)?"":"( $where ) and ")."`i`.`isList` = " . ($isList == true ? 1 : 0); } - if (empty($ruleWhere)) { - $xWhere=$where; - } else { - $xWhere=(empty($where)?$ruleWhere:"(".$where.") AND ".$ruleWhere); + if ($options["user"]) { + $ruleJoin = " INNER JOIN `tblUserGroupLink` as `l` on `l`.`groupId`=`i`.`id` AND `l`.`userId`='".$options["user"]->id."'"; } - - return ["where"=>$xWhere, "join"=>$ruleJoin]; + + return ["where"=>$where, "join"=>$ruleJoin]; } public function join(user $user) @@ -167,6 +164,36 @@ class userGroup extends baseClass implements externalCallable } } + ### REST API + + public static function API_POST_search(request $request) { + + $opts=[]; + if ($request->checkAccess("viewAllGroups")) { + $opts=[ + "user"=>$request->getRequestBodyItem("own",true)?$request->user:null, + "isList"=>$request->getRequestBodyItem("type")=="list", + ]; + } else if ($request->checkAccess("viewAllLists")) { + $opts = [ + "user"=>$request->getRequestBodyItem("own",true)?$request->user:null, + "isList"=>true, + ]; + } else { + $opts = [ + "user"=>$request->user, + "isList"=>true, + ]; + + } + return static::search( + $request->getRequestBodyItem("pattern"), + $request->getRequestBodyItem("pageSize"), + $request->getRequestBodyItem("page"), + $opts + ); + } + public static function API_GET_list(request $request) { if (! $request->user->checkAccess("adminUserGroups", "core")) { diff --git a/static/js/core/coreGroup.js b/static/js/core/coreGroup.js index b84eb5c..17c2693 100644 --- a/static/js/core/coreGroup.js +++ b/static/js/core/coreGroup.js @@ -190,7 +190,7 @@ function btnUserpAdd_click() { data: {pattern: request.term, pageSize: 10}, onSuccess: function(json) { let rv=[]; - $.each(json.data,function(key,val) { + $.each(json.data.result,function(key,val) { rv.push({id: val.id, value: val.fullName}); }); response(rv); diff --git a/static/js/core/lang_ru.js b/static/js/core/lang_ru.js index 76c881b..ae856c8 100644 --- a/static/js/core/lang_ru.js +++ b/static/js/core/lang_ru.js @@ -29,6 +29,7 @@ export var langItem={ set: "Установить", edit: "Изменить", copy: "Копировать", + copyHash: "Копировать указатель", paste: "Вставить", updated: "Обновлен", reload: "Обновить", diff --git a/static/js/core/login.js b/static/js/core/login.js index 728a03e..f621e2c 100644 --- a/static/js/core/login.js +++ b/static/js/core/login.js @@ -83,6 +83,9 @@ export function load() { }) }).appendTo("body"); + $("