May-12 API Update

This commit is contained in:
Pavel Dmitriev 2022-05-12 16:59:48 +03:00
parent a12a40c8b1
commit 797f5a4d8e
51 changed files with 274 additions and 160 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@
/temp-test /temp-test
/composer.lock /composer.lock
/vendor /vendor
.scannerwork

View File

@ -1,4 +1,4 @@
FROM mxfox.ru/chimera/fox-web-basic:latest AS prepare FROM mxfox.ru/mxfox/fox-web-basic:latest AS prepare
RUN apt-get update \ RUN apt-get update \
&& apt-get install curl -y \ && apt-get install curl -y \
@ -31,6 +31,6 @@ RUN rm -f composer.* \
&& rm -rf docker-build && rm -rf docker-build
FROM mxfox.ru/chimera/fox-web-basic:latest as build FROM mxfox.ru/mxfox/fox-web-basic:latest as build
COPY --from=prepare /var/www/html /var/www/html COPY --from=prepare /var/www/html /var/www/html
COPY docker-build/rootfs / COPY docker-build/rootfs /

View File

@ -105,7 +105,6 @@ try {
print(json_encode(["error"=>["errCode"=>500,"message"=>"Internal server error", "xCode"=>"ERR"]])); print(json_encode(["error"=>["errCode"=>500,"message"=>"Internal server error", "xCode"=>"ERR"]]));
header('HTTP/1.0 500 Internal server error', true, 500); header('HTTP/1.0 500 Internal server error', true, 500);
throw($e); throw($e);
exit;
} }
exit; exit;

View File

@ -26,7 +26,6 @@ $m = fox\modules::list();
$initUser=empty(config::get("INIT_USERNAME"))?"admin":config::get("INIT_USERNAME"); $initUser=empty(config::get("INIT_USERNAME"))?"admin":config::get("INIT_USERNAME");
$initPass=empty(config::get("INIT_PASSWORD"))?"chimera":config::get("INIT_PASSWORD"); $initPass=empty(config::get("INIT_PASSWORD"))?"chimera":config::get("INIT_PASSWORD");
//if (moduleInfo::getCount() ==0) {
// installing modules // installing modules
foreach ($m as $mod) { foreach ($m as $mod) {
if (array_key_exists($mod->name, modules::pseudoModules) && !$mod->getInstances()) { if (array_key_exists($mod->name, modules::pseudoModules) && !$mod->getInstances()) {
@ -35,7 +34,6 @@ $initPass=empty(config::get("INIT_PASSWORD"))?"chimera":config::get("INIT_PASSWO
print "OK\n"; print "OK\n";
} }
} }
//}
if (company::getCount()==0) { if (company::getCount()==0) {

56
cli/installPackages.php Normal file
View File

@ -0,0 +1,56 @@
<?php
use fox\modules;
use fox\config;
include(__DIR__."/../Autoloader.php");
if (strtolower(config::get("Environment"))=="development") {
print "Development mode. Package installation skipped.\n";
exit;
}
print "Packages installer started\n";
foreach (scandir(modules::packagesDir) as $file) {
if (!preg_match("/\.zip$/", $file)) {
continue;
}
if (! is_file(modules::packagesDir . "/" . $file)) {
continue;
}
// read config
$newModInfo=json_decode(file_get_contents("zip://".modules::packagesDir . "/" . $file."#module.json"));
// check if module present
$modInstalled=false;
$needUpdate=false;
if (file_exists(modules::modulesDir."/".$newModInfo->name) && file_exists(modules::modulesDir."/".$newModInfo->name."/module.json")) {
$exModInfo=json_decode(file_get_contents(modules::modulesDir."/".$newModInfo->name."/module.json"));
if (!empty($exModInfo)) {
$modInstalled=true;
$needUpdate=(property_exists($exModInfo, "hash") && $exModInfo->hash!=$newModInfo->hash);
}
}
print "Module ".$newModInfo->name.": ".($modInstalled?"Installed, ".($needUpdate?"Outdated":"Actual"):"Not installed").".\n";
if ($modInstalled && $needUpdate) {
system("rm -rf \"".modules::modulesDir."/".$newModInfo->name."\"");
}
if (!$modInstalled || $needUpdate) {
print "Install...";
$zip = new \ZipArchive();
$zip->open(modules::packagesDir . "/" . $file);
mkdir (modules::modulesDir."/".$newModInfo->name);
$zip->extractTo(modules::modulesDir."/".$newModInfo->name);
if (file_exists(modules::modulesDir."/".$newModInfo->name."/fox-start.d")) {
system("chmod a+x \"".modules::modulesDir."/".$newModInfo->name."/fox-start.d/\"*");
}
print "OK\n";
}
}
print "Packages installer completed\n";

View File

@ -2,6 +2,7 @@
"require" : { "require" : {
"aws/aws-sdk-php" : "^3.208", "aws/aws-sdk-php" : "^3.208",
"html2text/html2text" : "^4.3", "html2text/html2text" : "^4.3",
"phpmailer/phpmailer" : "~6.5.3" "phpmailer/phpmailer" : "~6.5.3",
"firebase/php-jwt" : "~6.1"
} }
} }

View File

@ -38,7 +38,7 @@ class UID extends baseClass implements stringExportable, stringImportable
public function __get($key) public function __get($key)
{ {
if (! empty($this->id) && $this->__loaded == false) { if (empty($this->id) && $this->__loaded) {
$this->fill($this->id); $this->fill($this->id);
} }
@ -80,8 +80,7 @@ class UID extends baseClass implements stringExportable, stringImportable
$sum2 = substr($code, 0, 1) + substr($code, 2, 1) + substr($code, 4, 1) + substr($code, 6, 1) + substr($code, 8, 1); $sum2 = substr($code, 0, 1) + substr($code, 2, 1) + substr($code, 4, 1) + substr($code, 6, 1) + substr($code, 8, 1);
$sum = $sum1 + $sum2; $sum = $sum1 + $sum2;
$ceil = ceil(($sum / 10)) * 10; $ceil = ceil(($sum / 10)) * 10;
$delta = $ceil - $sum; return $ceil - $sum;
return $delta;
} }
public static $sqlTable = "tblRegistry"; public static $sqlTable = "tblRegistry";

View File

@ -20,8 +20,7 @@ class auth extends baseClass implements noSqlMigration
$sql = sql::getConnection(); $sql = sql::getConnection();
$res = $sql->quickExec1Line("select * from `" . user::$sqlTable . "` where `login` = '" . common::clearInput($login) . "' and `secret` = '" . xcrypt::hash($password) . "'"); $res = $sql->quickExec1Line("select * from `" . user::$sqlTable . "` where `login` = '" . common::clearInput($login) . "' and `secret` = '" . xcrypt::hash($password) . "'");
if ($res) { if ($res) {
$u = new user($res); return new user($res);
return $u;
} else { } else {
return false; return false;
} }

View File

@ -17,6 +17,7 @@ use fox\foxException;
use fox\auth; use fox\auth;
use fox\authToken; use fox\authToken;
use fox\request; use fox\request;
use fox\foxRequestResult;
class login implements externalCallable class login implements externalCallable
{ {
@ -26,7 +27,7 @@ class login implements externalCallable
switch ($request->method) { switch ($request->method) {
case "POST": case "POST":
if ($request->authOK) { if ($request->authOK) {
return; throw new foxRequestResult("OK",200);
} }
if (! (gettype($request->requestBody) == "object" && property_exists($request->requestBody, "login") && property_exists($request->requestBody, "password"))) { if (! (gettype($request->requestBody) == "object" && property_exists($request->requestBody, "login") && property_exists($request->requestBody, "password"))) {
throw new foxException("Bad request", 400); throw new foxException("Bad request", 400);

View File

@ -49,7 +49,7 @@ class oauth implements externalCallable
case "POST": case "POST":
$profile = oAuthProfile::getByHash(common::clearInput($request->requestBody->hash)); $profile = oAuthProfile::getByHash(common::clearInput($request->requestBody->hash));
$oac = $profile->getClient(config::get("SITEPREFIX")."/auth/oauth"); $oac = $profile->getClient(config::get("SITEPREFIX")."/auth/oauth");
$xTokens=$oac->getTokenByCode(common::clearInput($request->requestBody->code)); $oac->getTokenByCode(common::clearInput($request->requestBody->code));
$userInfo=$oac->getUserInfo(); $userInfo=$oac->getUserInfo();
$userRefId=$profile->id.":".$userInfo->sub; $userRefId=$profile->id.":".$userInfo->sub;
$u=user::getByRefID("oauth",$userRefId); $u=user::getByRefID("oauth",$userRefId);
@ -64,8 +64,9 @@ class oauth implements externalCallable
"expire" => $t->expireStamp->isNull() ? "Never" : $t->expireStamp "expire" => $t->expireStamp->isNull() ? "Never" : $t->expireStamp
]; ];
return $u;
break; break;
default:
throw new foxException("Method not implemented",405);
} }
} }
} }

View File

@ -49,7 +49,6 @@ class register implements externalCallable {
if (!$u) { if (!$u) {
$u = new user(); $u = new user();
// $u->login=uniqid();
$u->eMail=$eMail; $u->eMail=$eMail;
$u->authType="oauth"; $u->authType="oauth";
$u->authRefId=$userRefId; $u->authRefId=$userRefId;

View File

@ -16,6 +16,7 @@ use fox\externalCallable;
use fox\foxException; use fox\foxException;
use fox\request; use fox\request;
use fox\modules; use fox\modules;
use fox\foxRequestResult;
class session implements externalCallable class session implements externalCallable
{ {
@ -29,13 +30,13 @@ class session implements externalCallable
} }
$request->token->delete(); $request->token->delete();
return; foxRequestResult::throw(200,"Deleted");
case "GET": case "GET":
if ($request->authOK) { if ($request->authOK) {
$modules=[]; $modules=[];
$i = 0; $i = 0;
foreach (modules::listInstalled() as $mod) { foreach (modules::listInstalled() as $mod) {
if (array_search("menu", $mod->features) !== false && $request->user->checkAccess($mod->globalAccessKey, $mod->name) && ! empty($mod->menuItem)) { if ($request->user->checkAccess($mod->globalAccessKey, $mod->name)) {
$i ++; $i ++;
$modules[($mod->modPriority * 100) + $i] = [ $modules[($mod->modPriority * 100) + $i] = [
"name" => $mod->name, "name" => $mod->name,
@ -54,9 +55,11 @@ class session implements externalCallable
"modules" => $modules "modules" => $modules
]; ];
} }
;
throw new foxException("Unauthorized", 401); throw new foxException("Unauthorized", 401);
break; break;
default:
throw new foxException("Method not allowe", 405);
break;
} }
} }
} }

View File

@ -155,9 +155,7 @@ class authToken extends baseClass
} else if ($t->token1 == $token1 && $t->token2 != $token2 && $token2 != $t->token2b) { } else if ($t->token1 == $token1 && $t->token2 != $token2 && $token2 != $t->token2b) {
// token2 failed - token are compromised // token2 failed - token are compromised
trigger_error("Token #".$t->id." are compromised!"); trigger_error("Token #".$t->id." are compromised!");
// $t->delete(); $t->delete();
} else {
} }
$sql->quickExec("COMMIT"); $sql->quickExec("COMMIT");
@ -189,7 +187,6 @@ class authToken extends baseClass
$t->expireStamp = empty($expireInDays) ? (new time()) : (new time(time() + ($expireInDays * 86400))); $t->expireStamp = empty($expireInDays) ? (new time()) : (new time(time() + ($expireInDays * 86400)));
$t->renewStamp = empty($renewTTL) ? (new time()) : (new time(time() + ($renewTTL * 60))); $t->renewStamp = empty($renewTTL) ? (new time()) : (new time(time() + ($renewTTL * 60)));
;
for ($i = 0; $i < 32; $i ++) { for ($i = 0; $i < 32; $i ++) {
$token = substr(preg_replace("/[-_+=\\/]/", "", base64_encode(random_bytes(64))), 0, 64); $token = substr(preg_replace("/[-_+=\\/]/", "", base64_encode(random_bytes(64))), 0, 64);
@ -217,7 +214,6 @@ class authToken extends baseClass
$renewTTL = config::get("TOKEN_RENEW_" . $this->type) === null ? static::tokenTypes[$this->type]["renewTTL"] : config::get("TOKEN_RENEW_" . $this->type); $renewTTL = config::get("TOKEN_RENEW_" . $this->type) === null ? static::tokenTypes[$this->type]["renewTTL"] : config::get("TOKEN_RENEW_" . $this->type);
$this->renewStamp = empty($renewTTL) ? (new time()) : (new time(time() + ($renewTTL * 60))); $this->renewStamp = empty($renewTTL) ? (new time()) : (new time(time() + ($renewTTL * 60)));
;
$this->token2b = $this->token2; $this->token2b = $this->token2;
$this->token2 = substr(preg_replace("/[-_+=\\/]/", "", base64_encode(random_bytes(64))), 0, 64); $this->token2 = substr(preg_replace("/[-_+=\\/]/", "", base64_encode(random_bytes(64))), 0, 64);

View File

@ -100,7 +100,7 @@ class baseClass extends dbStoredBase implements \JsonSerializable, jsonImportabl
case "object": case "object":
if (! empty($val::$SQLType)) { if (! empty($val::$SQLType)) {
$type = $val::$SQLType; $type = $val::$SQLType;
} elseif (($val instanceof stringExportable)) { } elseif ($val instanceof stringExportable) {
$type = "VARCHAR(255)"; $type = "VARCHAR(255)";
} elseif ($val instanceof \JsonSerializable) { } elseif ($val instanceof \JsonSerializable) {
$type = "VARCHAR(255)"; $type = "VARCHAR(255)";
@ -134,18 +134,19 @@ class baseClass extends dbStoredBase implements \JsonSerializable, jsonImportabl
if ($this->sql === null) { if ($this->sql === null) {
$this->sql = sql::getConnection(); $this->sql = sql::getConnection();
} }
return;
} }
protected function __xConstruct() protected function __xConstruct()
{} {
return true;
}
public function __construct($id = null, ?namespace\sql $sql = null, $prefix = null, $settings = null) public function __construct($id = null, ?namespace\sql $sql = null, $prefix = null, $settings = null)
{ {
# How to call from child template: # How to call from child template:
# parent::__construct($id, $sql, $prefix, $settings); # parent::__construct($id, $sql, $prefix, $settings);
$this->__settings = $settings; $this->__settings = $settings;
if (empty($this::$sqlSelectTemplate) and ! empty($this::$sqlTable)) { if (empty($this::$sqlSelectTemplate) && ! empty($this::$sqlTable)) {
$this->__sqlSelectTemplate = "select * from `" . $this::$sqlTable . "` as `i`"; $this->__sqlSelectTemplate = "select * from `" . $this::$sqlTable . "` as `i`";
} else { } else {
$this->__sqlSelectTemplate = $this::$sqlSelectTemplate; $this->__sqlSelectTemplate = $this::$sqlSelectTemplate;
@ -442,7 +443,6 @@ class baseClass extends dbStoredBase implements \JsonSerializable, jsonImportabl
} }
} else { } else {
throw new \Exception("property $key not availiable for read in class " . get_class($this), 595); throw new \Exception("property $key not availiable for read in class " . get_class($this), 595);
break;
} }
} }
} }
@ -504,7 +504,7 @@ class baseClass extends dbStoredBase implements \JsonSerializable, jsonImportabl
if (($this->__get($key)) instanceof \JsonSerializable) { if (($this->__get($key)) instanceof \JsonSerializable) {
$rv[$key] = $this->__get($key); $rv[$key] = $this->__get($key);
} elseif (($this->__get($key)) instanceof stringExportable) { } elseif (($this->__get($key)) instanceof stringExportable) {
if (($this->__get($key)->isNull())) { if ($this->__get($key)->isNull()) {
$rv[$key] = null; $rv[$key] = null;
} else { } else {
$rv[$key] = (string) ($this->__get($key)); $rv[$key] = (string) ($this->__get($key));
@ -558,7 +558,7 @@ class baseClass extends dbStoredBase implements \JsonSerializable, jsonImportabl
break; break;
default: default:
continue 2; break;
} }
} }
@ -583,9 +583,10 @@ class baseClass extends dbStoredBase implements \JsonSerializable, jsonImportabl
$sqlQueryString=$ref->sqlSelectTemplate.(empty($join)?"":" ".$join).(empty($where)?"":" WHERE ".$where).(empty($limit)?"":" ".$limit); $sqlQueryString=$ref->sqlSelectTemplate.(empty($join)?"":" ".$join).(empty($where)?"":" WHERE ".$where).(empty($limit)?"":" ".$limit);
$res=$sql->quickExec($sqlQueryString); $res=$sql->quickExec($sqlQueryString);
$rv=[]; $rv=new searchResult();
$rv->setIndexByPage($page, $pageSize);
while ($row=mysqli_fetch_assoc($res)) { while ($row=mysqli_fetch_assoc($res)) {
$rv[]=new static($row); $rv->push(new static($row));
} }
return $rv; return $rv;
} }

View File

@ -14,10 +14,19 @@ namespace fox;
class baseModule class baseModule
{ {
/**
* @deprecated - moved into module.json
*/
public static $title = "Basic Module Template"; public static $title = "Basic Module Template";
/**
* @deprecated - moved into module.json
*/
public static $desc = "Базовый класс модуля-заглушки"; public static $desc = "Базовый класс модуля-заглушки";
/**
* @deprecated - moved into module.json
*/
public static $version = "0.0.0"; public static $version = "0.0.0";
public static $type = "fake"; public static $type = "fake";
@ -71,8 +80,6 @@ class baseModule
public static function getModInfo(): moduleInfo public static function getModInfo(): moduleInfo
{ {
$mi = new moduleInfo(); $mi = new moduleInfo();
$mi->title = static::$title;
$mi->modVersion = static::$version;
$mi->name = $mi->namespace = substr(static::class, 0, strrpos(static::class, '\\')); $mi->name = $mi->namespace = substr(static::class, 0, strrpos(static::class, '\\'));
$mi->features = static::$features; $mi->features = static::$features;
$mi->isTemplate = true; $mi->isTemplate = true;

View File

@ -41,7 +41,7 @@ class cache
if (empty($port)) { if (empty($port)) {
$port = config::get("cachePort"); $port = config::get("cachePort");
} }
;
if (empty($port)) { if (empty($port)) {
$port = 11211; $port = 11211;
} }
@ -104,8 +104,7 @@ class cache
if ($xval==null || $xval=="null") { return null; } if ($xval==null || $xval=="null") { return null; }
$rv= json_decode($this->mcd->get($this->prefix . "." . $key), $array); $rv= json_decode($this->mcd->get($this->prefix . "." . $key), $array);
if ($rv !== null) { return $rv; } if ($rv !== null) { return $rv; }
$rv= json_decode(xcrypt::decrypt($this->mcd->get($this->prefix . "." . $key)), $array); return json_decode(xcrypt::decrypt($this->mcd->get($this->prefix . "." . $key)), $array);
return $rv;
} }
public function del($key) { public function del($key) {

View File

@ -42,7 +42,6 @@ class common
if (isset($_GET[$name])) { if (isset($_GET[$name])) {
$val = preg_replace('![^' . $regex . ']+!', '', $_GET[$name]); $val = preg_replace('![^' . $regex . ']+!', '', $_GET[$name]);
} }
;
} }
} else { } else {
@ -52,11 +51,9 @@ class common
} else { } else {
$val = ""; $val = "";
} }
if ($val == "") { if ($val == "" && isset($_GET[$name])) {
if (isset($_GET[$name])) {
$val = preg_replace("![\'\"]+!", '\"', $_GET[$name]); $val = preg_replace("![\'\"]+!", '\"', $_GET[$name]);
} }
}
} else { } else {
if (isset($_POST[$name])) { if (isset($_POST[$name])) {
$val = $_POST[$name]; $val = $_POST[$name];
@ -98,17 +95,13 @@ class common
mt_srand((double) microtime() * 10000); // optional for php 4.2.0 and up. mt_srand((double) microtime() * 10000); // optional for php 4.2.0 and up.
$charid = strtoupper(md5(uniqid(rand(), true))); $charid = strtoupper(md5(uniqid(rand(), true)));
$hyphen = chr(45); // "-" $hyphen = chr(45); // "-"
$uuid = 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 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 $uuid;
} }
static function getGUID() static function getGUID()
{ {
$cUuid = getGUIDc(); return chr(123) . getGUIDc() . chr(125);
$uuid = chr(123) . // "{"
$cUuid . chr(125); // "}"
return $uuid;
} }
static function fullname2qname($first, $mid, $last) static function fullname2qname($first, $mid, $last)
@ -119,7 +112,6 @@ class common
static function text2html($src) static function text2html($src)
{ {
$src = preg_replace("/[\n]/", "</br>", $src); $src = preg_replace("/[\n]/", "</br>", $src);
// $src=preg_replace("/[\cr\<\>]/"," ",$src);
return $src; return $src;
} }

View File

@ -68,7 +68,8 @@ class config extends dbStoredBase
"FOX_DEFAULT_LANGUAGE", "FOX_DEFAULT_LANGUAGE",
"FOX_DEFAULT_MODULE", "FOX_DEFAULT_MODULE",
"FOX_SESSION_RENEW_SEC", "FOX_SESSION_RENEW_SEC",
"FOX_ALLOW_REGISTER" "FOX_ALLOW_REGISTER",
"FOX_ENVIRONMENT",
]; ];
static function get($key, $module = "core") static function get($key, $module = "core")

View File

@ -74,7 +74,7 @@ class confirmCode extends baseClass {
protected function validateSave() protected function validateSave()
{ {
if ($this->issueStamp->isNull()) {$this->issueStamp=time::current();}; if ($this->issueStamp->isNull()) {$this->issueStamp=time::current();}
if ($this->expireStamp->isNull()) {$this->expireStamp=time::current()->addSec(static::defaultTTL);} if ($this->expireStamp->isNull()) {$this->expireStamp=time::current()->addSec(static::defaultTTL);}
if ($this->code==null) { $this->code=(common::genPasswd(4,[0,1,2,3,4,5,6,7,8,9]));} if ($this->code==null) { $this->code=(common::genPasswd(4,[0,1,2,3,4,5,6,7,8,9]));}
if (empty($this->instance) || empty($this->class) || empty($this->operation) || empty($this->reference)) { if (empty($this->instance) || empty($this->class) || empty($this->operation) || empty($this->reference)) {

View File

@ -60,7 +60,7 @@ class cronDb {
} }
$rv=[]; $rv=[];
while ($row = $r->fetchArray(SQLITE3_ASSOC)) { while ($row = $r->fetchArray(SQLITE3_ASSOC)) {
array_push($rv, $row);; array_push($rv, $row);
} }
return $rv; return $rv;

View File

@ -46,11 +46,6 @@ class errorPage
exit(); exit();
} }
$mod_name = config::get("defaultLoginModule");
if (! $mod_name) {
$mod_name = "core";
}
static::show($error_code, $error_desc, true); static::show($error_code, $error_desc, true);
exit(); exit();
} }

View File

@ -16,7 +16,7 @@ use Exception;
class fileConverter class fileConverter
{ {
public static function convert($src, $dst = null, $type, $url = null) public static function convert($src, $dst, $type, $url = null)
{ {
if (empty($url)) { if (empty($url)) {
$url = config::get("converterURL"); $url = config::get("converterURL");
@ -29,8 +29,6 @@ class fileConverter
throw new \Exception("Invalid source file $src"); throw new \Exception("Invalid source file $src");
} }
$boundary = '------------chimera---' . substr(md5(rand(0, 32000) . '---fox-----'), 0, 10);
// "засечка" :P // "засечка" :P
$boundary = md5(rand(0, 32000)); $boundary = md5(rand(0, 32000));

View File

@ -81,8 +81,8 @@ class mailAccount extends baseClass implements externalCallable {
case "password": return xcrypt::decrypt($this->__password); case "password": return xcrypt::decrypt($this->__password);
case "rxLogin": return $this->login; case "rxLogin": return $this->login;
case "rxPassword": return xcrypt::decrypt($this->__password); case "rxPassword": return xcrypt::decrypt($this->__password);
case "rxLogin": return $this->login; case "txLogin": return $this->login;
case "rxPassword": return xcrypt::decrypt($this->__password); case "txPassword": return xcrypt::decrypt($this->__password);
default: return parent::__get($key); default: return parent::__get($key);
} }
} }
@ -161,7 +161,7 @@ class mailAccount extends baseClass implements externalCallable {
throw new foxException("Forbidden", 403); throw new foxException("Forbidden", 403);
} }
return static::search(); return static::search()->result;
} }
public static function API_DELETE(request $request) { public static function API_DELETE(request $request) {

View File

@ -23,7 +23,7 @@ class mailAddress {
$this->__set("address", $address); $this->__set("address", $address);
} else { } else {
$res=[]; $res=[];
$name = preg_replace('!^[\"\ \t]*|[\"\ \t]*$!', '', $name); $name = preg_replace('!(^[\"\ \t]*)|([\"\ \t]*$)!', '', $name);
if(preg_match("/([^\<\>]*) \<([^\<\>]*)\>/", $name, $res)) { if(preg_match("/([^\<\>]*) \<([^\<\>]*)\>/", $name, $res)) {
$this->address=$res[2]; $this->address=$res[2];
$this->name=$res[1]; $this->name=$res[1];
@ -36,7 +36,7 @@ class mailAddress {
} }
} }
$this->name = preg_replace('!^[\"]*|[\"]*$!', '', $this->name); $this->name = preg_replace('!(^[\"]*)|([\"]*$)!', '', $this->name);
} }

View File

@ -185,17 +185,17 @@ class mailMessage extends baseClass {
$ref = explode(" ", $val); $ref = explode(" ", $val);
$this->refIds=[]; $this->refIds=[];
foreach ($ref as $ref_item) { foreach ($ref as $ref_item) {
$ref_item=preg_replace("!^\<|\>$!", '', $ref_item); $ref_item=preg_replace("!(^\<)|(\>$)!", '', $ref_item);
array_push($this->refIds, $ref_item); array_push($this->refIds, $ref_item);
} }
break; break;
case "inReplyTo": case "inReplyTo":
$this->inReptyTo=preg_replace("!^\<|\>$!", '', $val); $this->inReptyTo=preg_replace("!(^\<)|(\>$)!", '', $val);
break; break;
case "messageId": case "messageId":
$this->messageId=preg_replace("!^\<|\>$!", '', $val); $this->messageId=preg_replace("!(^\<)|(\>$)!", '', $val);
break; break;
case "subject": case "subject":
$this->__subject=base64_encode($val); $this->__subject=base64_encode($val);
@ -301,7 +301,6 @@ class mailMessage extends baseClass {
if ($this->account->txProto!='smtp' || $this->account->txServer == null) { if ($this->account->txProto!='smtp' || $this->account->txServer == null) {
throw new \Exception("This account can't send messages"); throw new \Exception("This account can't send messages");
return false;
} }
$mail = new PHPMailer(true); $mail = new PHPMailer(true);
$mail->CharSet = PHPMailer::CHARSET_UTF8; $mail->CharSet = PHPMailer::CHARSET_UTF8;

View File

@ -23,7 +23,7 @@ class settings implements externalCallable
{ {
public static function APICall(request $request) public static function APICall(request $request)
{ {
$profiles = oAuthProfile::search(); $profiles = oAuthProfile::search()->result;
$oauth=[]; $oauth=[];
foreach ($profiles as $p) { foreach ($profiles as $p) {
if ($p->enabled) { if ($p->enabled) {

View File

@ -226,6 +226,17 @@ class moduleInfo extends baseClass implements externalCallable
return $modsInstalled[$modInstanceName]; return $modsInstalled[$modInstanceName];
} }
public static function getByFeature(string $feature) {
$rv=[];
foreach(moduleInfo::getAll() as $mod) {
if (array_search($feature, $mod->features) !==false) {
$rv[]=$mod;
}
}
return $rv;
}
public function getInstances() public function getInstances()
{ {
if (! $this->isTemplate) { if (! $this->isTemplate) {
@ -245,6 +256,11 @@ class moduleInfo extends baseClass implements externalCallable
public static function load(string $modName) public static function load(string $modName)
{} {}
public function newClass() {
$ref=$this->namespace.'\module';
return new $ref();
}
public function export() { public function export() {
$rv=parent::export(); $rv=parent::export();
if ($this->isTemplate) { if ($this->isTemplate) {
@ -362,7 +378,7 @@ class moduleInfo extends baseClass implements externalCallable
$mod->features[]=common::clearInput($request->requestBody->feature); $mod->features[]=common::clearInput($request->requestBody->feature);
$mod->features=array_values($mod->features); $mod->features=array_values($mod->features);
$mod->save(); $mod->save();
static::log($request->instance,__FUNCTION__, "feature ".common::clearInput($request->requestBody->feature)." set for module ".$mod->name,$request->user,"module",$user->id,null,logEntry::sevInfo); static::log($request->instance,__FUNCTION__, "feature ".common::clearInput($request->requestBody->feature)." set for module ".$mod->name,$request->user,"module",$mod->id,null,logEntry::sevInfo);
foxRequestResult::throw(201, "Created"); foxRequestResult::throw(201, "Created");
} }
foxRequestResult::throw(201, "Created"); foxRequestResult::throw(201, "Created");
@ -370,7 +386,7 @@ class moduleInfo extends baseClass implements externalCallable
case "config": case "config":
config::set(common::clearInput($request->requestBody->key), $request->requestBody->value, $mod->name); config::set(common::clearInput($request->requestBody->key), $request->requestBody->value, $mod->name);
static::log($request->instance,__FUNCTION__, "config key ".common::clearInput($request->requestBody->key)." set for module ".$mod->name,$request->user,"module",$user->id,null,logEntry::sevInfo); static::log($request->instance,__FUNCTION__, "config key ".common::clearInput($request->requestBody->key)." set for module ".$mod->name,$request->user,"module",$mod->id,null,logEntry::sevInfo);
foxRequestResult::throw(201, "Created"); foxRequestResult::throw(201, "Created");
break; break;
default: default:

View File

@ -13,6 +13,8 @@ namespace fox;
*/ */
class modules implements externalCallable class modules implements externalCallable
{ {
public const modulesDir=__DIR__ . "/../../modules/";
public const packagesDir=__DIR__ . "/../../packages/";
// not implemented yet // not implemented yet
public const pseudoModules = [ public const pseudoModules = [
@ -138,8 +140,18 @@ class modules implements externalCallable
if (array_key_exists($modName, static::pseudoModules)) { if (array_key_exists($modName, static::pseudoModules)) {
$modInfo = new moduleInfo(static::pseudoModules[$modName]); $modInfo = new moduleInfo(static::pseudoModules[$modName]);
} else { } else {
try {
$modClass = $modName . "\module"; $modClass = $modName . "\module";
$modInfo = (new $modClass())::getModInfo(); $modInfo = (new $modClass())::getModInfo();
$modDesc=json_decode(file_get_contents(static::modulesDir . "/" . $modName . "/module.json"));
if (empty($modDesc)) { throw new foxException("Unable to read module.json"); }
if ($modDesc->name != $modInfo->name) { throw new foxException("Module name mismatch for ".$modInfo->name); }
$modInfo->title=$modDesc->title;
$modInfo->modVersion=$modDesc->version;
} catch (\Exception $e) {
trigger_error($e->getMessage());
continue;
}
} }
$rv[$modInfo->name] = $modInfo; $rv[$modInfo->name] = $modInfo;
} }
@ -152,20 +164,27 @@ class modules implements externalCallable
return moduleInfo::getAll(); return moduleInfo::getAll();
} }
public static function getByFeature(string $feature) {
return moduleInfo::getByFeature($feature);
}
public static function scan() public static function scan()
{ {
$rv = []; $rv = [];
foreach (static::pseudoModules as $key => $val) { foreach (static::pseudoModules as $key => $val) {
$rv[] = $key; $rv[] = $key;
} }
foreach (scandir(__DIR__ . "/../../modules/") as $dir) { foreach (scandir(static::modulesDir) as $dir) {
if (preg_match("/^[.]/", $dir)) { if (preg_match("/^[.]/", $dir)) {
continue; continue;
} }
if (! is_dir(__DIR__ . "/../../modules/" . $dir)) { if (! is_dir(static::modulesDir . $dir)) {
continue; continue;
} }
if (! file_exists(__DIR__ . "/../../modules/" . $dir . "/module.php") && ! file_exists(__DIR__ . "/../../modules/" . $dir . "/Autoloader.php")) { if (! file_exists(static::modulesDir . $dir . "/module.json")) {
continue;
}
if (! file_exists(static::modulesDir . $dir . "/module.php") && ! file_exists(static::modulesDir . $dir . "/Autoloader.php")) {
continue; continue;
} }
$rv[] = $dir; $rv[] = $dir;
@ -226,7 +245,7 @@ class modules implements externalCallable
$mod->modPriority=$modPriority; $mod->modPriority=$modPriority;
} }
$mod->save(); $mod->save();
static::log($request->instance,__FUNCTION__, "Module ".$mod->name." installed",$request->user,"module",$mod->id,null,logEntry::sevInfo); logEntry::add($request->instance, static::class, __FUNCTION__, null, "Module ".$mod->name." installed", "INFO", $request->user, "module", $mod->id);
foxRequestResult::throw(201, "Created", $mod); foxRequestResult::throw(201, "Created", $mod);
} }

View File

@ -145,7 +145,6 @@ class oAuthClient {
} else { } else {
trigger_error(json_encode($res)); trigger_error(json_encode($res));
throw new foxException("Invalid token"); throw new foxException("Invalid token");
exit;
} }
} }

View File

@ -75,7 +75,7 @@ class oAuthProfile extends baseClass implements externalCallable {
if (! $request->user->checkAccess("adminAuthMethods", "core")) { if (! $request->user->checkAccess("adminAuthMethods", "core")) {
throw new foxException("Forbidden", 403); throw new foxException("Forbidden", 403);
} }
return static::search(); return static::search()->result;
} }
public static function APIX_GET_disable(request $request) { public static function APIX_GET_disable(request $request) {

31
core/fox/searchResult.php Normal file
View File

@ -0,0 +1,31 @@
<?php
namespace fox;
class searchResult {
public $page=0;
public $pages=0;
public $result=[];
public $count=0;
protected $idx=1;
public function setIndex($idx) {
$this->idx = $idx;
}
public function push($val) {
$this->result[$this->idx] = $val;
$this->idx++;
$this->count++;
}
public function __construct($idx=null) {
if (isset($idx)) {
$this->idx = $idx;
}
}
public function setIndexByPage($page=null, $pagesize=null) {
if ($page===null) { $page = $this->page; }
$this->idx = (($page-1)*$pagesize)+1;
}
}
?>

View File

@ -109,7 +109,6 @@ class sql
mysqli_set_charset($this->mysqli, "utf8"); mysqli_set_charset($this->mysqli, "utf8");
if (! $this->mysqli) { // Если дескриптор равен 0 соединение не установлено if (! $this->mysqli) { // Если дескриптор равен 0 соединение не установлено
throw new Exception("SQL Connection to $this->server failed"); throw new Exception("SQL Connection to $this->server failed");
exit();
} }
$this->connected = true; $this->connected = true;
} }
@ -135,7 +134,6 @@ class sql
} }
; ;
return null; return null;
exit();
} }
return $result; return $result;
} }
@ -194,7 +192,6 @@ class sql
if (! $this->stmt) { if (! $this->stmt) {
$err = 'ERR:EXEC 1P' . mysqli_errno($this->mysqli) . ' ' . mysqli_error($this->mysqli); $err = 'ERR:EXEC 1P' . mysqli_errno($this->mysqli) . ' ' . mysqli_error($this->mysqli);
throw new Exception($err, mysqli_errno($this->mysqli)); throw new Exception($err, mysqli_errno($this->mysqli));
exit();
} }
call_user_func_array(array( call_user_func_array(array(
$this->stmt, $this->stmt,
@ -205,7 +202,6 @@ class sql
$errNo = mysqli_errno($this->mysqli); $errNo = mysqli_errno($this->mysqli);
$this->stmt->close(); $this->stmt->close();
throw new Exception($err, $errNo); throw new Exception($err, $errNo);
exit();
} }
return true; return true;
} }
@ -218,7 +214,6 @@ class sql
$this->stmt->close(); $this->stmt->close();
} }
throw new \Exception('ERR:EXEC 3P' . mysqli_errno($this->mysqli) . ' ' . mysqli_error($this->mysqli), mysqli_errno($this->mysqli)); throw new \Exception('ERR:EXEC 3P' . mysqli_errno($this->mysqli) . ' ' . mysqli_error($this->mysqli), mysqli_errno($this->mysqli));
exit();
} }
$this->stmt->close(); $this->stmt->close();
return true; return true;
@ -232,9 +227,9 @@ class sql
function paramAdd($sqlParamName, $paramValue, $setNull = false) function paramAdd($sqlParamName, $paramValue, $setNull = false)
{ {
if ($this->queryType == "insert") { if ($this->queryType == "insert") {
return $this->paramAddInsert($sqlParamName, $paramValue, $setNull); $this->paramAddInsert($sqlParamName, $paramValue, $setNull);
} elseif ($this->queryType == "update") { } elseif ($this->queryType == "update") {
return $this->paramAddUpdate($sqlParamName, $paramValue, $setNull); $this->paramAddUpdate($sqlParamName, $paramValue, $setNull);
} }
} }

View File

@ -305,7 +305,7 @@ class user extends baseClass implements externalCallable
if (! $request->user->checkAccess("adminUsers", "core")) { if (! $request->user->checkAccess("adminUsers", "core")) {
throw new foxException("Forbidden", 403); throw new foxException("Forbidden", 403);
} }
return static::search(); return static::search()->result;
} }
public static function API_POST_search(request $request) { public static function API_POST_search(request $request) {
@ -315,7 +315,7 @@ class user extends baseClass implements externalCallable
$pageSize=common::clearInput($request->requestBody->pageSize,"0-9"); $pageSize=common::clearInput($request->requestBody->pageSize,"0-9");
if (empty($pageSize)) { $pageSize=$request->user->settings["pageSize"];} if (empty($pageSize)) { $pageSize=$request->user->settings["pageSize"];}
return static::search(common::clearInput($request->requestBody->pattern), $pageSize); return static::search(common::clearInput($request->requestBody->pattern), $pageSize)->result;
} }
@ -330,7 +330,7 @@ class user extends baseClass implements externalCallable
public static function API_GET_sendEMailConfirmation(request $request) { public static function API_GET_sendEMailConfirmation(request $request) {
$request->user->sendEMailConfirmation(); $request->user->sendEMailConfirmation();
static::log($request->instance,__FUNCTION__, "mailConfirmation sent for user ".$user->login,$request->user,"user",$user->id,null,logEntry::sevInfo); static::log($request->instance,__FUNCTION__, "mailConfirmation sent for user ".$request->user->login,$request->user,"user",$request->user->id,null,logEntry::sevInfo);
} }
public static function API_POST_validateEMailCode(request $request) { public static function API_POST_validateEMailCode(request $request) {
@ -341,21 +341,6 @@ class user extends baseClass implements externalCallable
foxException::throw("ERR", "Validation failed", 400); foxException::throw("ERR", "Validation failed", 400);
} }
} }
public static function APICall(request $request) {
if (!empty($request->function)) {
throw new foxException("Method not allowed",405);
}
switch ($request->method) {
default:
throw new foxException("Method not allowed",405);
}
}
} }
?> ?>

View File

@ -163,7 +163,7 @@ class userGroup extends baseClass implements externalCallable
if (! $request->user->checkAccess("adminUserGroups", "core")) { if (! $request->user->checkAccess("adminUserGroups", "core")) {
throw new foxException("Forbidden", 403); throw new foxException("Forbidden", 403);
} }
return static::search(); return static::search()->result;
} }
public static function API_POST_members(request $request) public static function API_POST_members(request $request)
@ -223,7 +223,7 @@ class userGroup extends baseClass implements externalCallable
case "PUT": case "PUT":
$grName=common::clearInput($request->requestBody->name); $grName=common::clearInput($request->requestBody->name);
$groups = userGroup::search($grName); $groups = userGroup::search($grName)->result;
foreach ($groups as $group) { foreach ($groups as $group) {
if (trim(strtolower($group->name))==trim(strtolower($grName))) { if (trim(strtolower($group->name))==trim(strtolower($grName))) {
foxException::throw("ERR", "Already exists", 409, "GAX"); foxException::throw("ERR", "Already exists", 409, "GAX");

View File

@ -158,7 +158,7 @@ class userGroupMembership extends baseClass implements externalCallable
$res=static::search(null,$pageSize,$page,[ $res=static::search(null,$pageSize,$page,[
"user"=>$user, "user"=>$user,
"group"=>$group, "group"=>$group,
]); ])->result;
$rv=[]; $rv=[];
foreach ($res as $ugm) { foreach ($res as $ugm) {

View File

@ -118,7 +118,7 @@ class userInvitation extends baseClass implements externalCallable {
} }
public static function API_GET_list(request $request) { public static function API_GET_list(request $request) {
return static::search(); return static::search()->result;
} }
public static function APIX_GET_reSend(request $request) { public static function APIX_GET_reSend(request $request) {

View File

@ -1,3 +1,3 @@
FROM mxfox.ru/chimera/fox-web-basic:latest FROM mxfox.ru/mxfox/fox-web-basic:latest
COPY . /var/www/html COPY . /var/www/html
COPY docker-build/rootfs / COPY docker-build/rootfs /

View File

@ -35,8 +35,9 @@ if (array_search($req[1], $jsons)!==false) {
} }
?> ?>
<!DOCTYPE>
<html class=login> <html lang="en" class=login>
<head><title>Error <?php print $code; ?></title></head>
<body class=login style=" <body class=login style="
background-image: url(/static/theme/chimera/img/chimera_logo.svg); background-image: url(/static/theme/chimera/img/chimera_logo.svg);
@ -48,7 +49,7 @@ if (array_search($req[1], $jsons)!==false) {
background-position-y: center; background-position-y: center;
background-color: #150007;"> background-color: #150007;">
<div style=' text-align: center; width: 100%; heigth: 100%;'> <div style=' text-align: center; width: 100%; height: 100%;'>
</div> </div>
@ -56,7 +57,6 @@ if (array_search($req[1], $jsons)!==false) {
border: 2px solid red; border: 2px solid red;
background-color: rgba(0, 0, 0, 0.85); background-color: rgba(0, 0, 0, 0.85);
margin: 0;
padding: 70 0 0 0; padding: 70 0 0 0;
position: absolute; position: absolute;
left: calc(50% - 250px); left: calc(50% - 250px);
@ -68,7 +68,9 @@ if (array_search($req[1], $jsons)!==false) {
vertical-align: center; vertical-align: center;
font-family: 'Fira Mono', monospace; font-family: 'Fira Mono', monospace;
font-weight: 200; font-weight: 200;
font-size: 32px; color: #FF3500; margin: 1%"> font-size: 32px;
color: #FF3500;
margin: 1%">
<?php <?php
print "ERROR: $code<br/>"; print "ERROR: $code<br/>";
if (array_key_exists($code, $codes)) { if (array_key_exists($code, $codes)) {

View File

@ -14,7 +14,6 @@
if (php_sapi_name() != 'cli') { if (php_sapi_name() != 'cli') {
throw new Exception("This script can be run via CLI only"); throw new Exception("This script can be run via CLI only");
exit;
} }
use fox\moduleInfo; use fox\moduleInfo;
@ -134,7 +133,7 @@ while(($xpid=pcntl_wait($status,WNOHANG)) >=0) {
foreach($pids as $pid=>&$ttl) { foreach($pids as $pid=>&$ttl) {
if ($ttl < $ttlc) { if ($ttl < $ttlc) {
print "Kill PID ".$pid." by TTL\n"; print "Kill PID ".$pid." by TTL\n";
var_dump(posix_kill($pid, SIGKILL)); posix_kill($pid, SIGKILL);
$ttl+=5; $ttl+=5;
} }
} }

View File

@ -1,4 +1,5 @@
#!/bin/bash #!/bin/bash
php /var/www/html/cli/installPackages.php
php /var/www/html/cli/migration.php php /var/www/html/cli/migration.php
php /var/www/html/cli/initialize.php php /var/www/html/cli/initialize.php

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html lang="en">
<head> <head>
<title>Chimera Fox</title> <title>Chimera Fox</title>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">

View File

@ -1,4 +1,4 @@
# Modules Folder # Modules Folder
This folder must be empty and don't used for any data except modules subfolders. This folder must be empty and don't used for any data except modules subfolders.
Modules must compliant FoxAPImk2. Modules must compliant FoxAPImk2.
Modules may be added as mapped-folder for docker containers or prebuilt in it. Modules may be prebuilt in docker image or placed as packages into `packages` folder - it will be unpacked automatically while startup procedure.

4
packages/README.md Normal file
View File

@ -0,0 +1,4 @@
# Packages Folder
This folder must be empty and don't used for any data except modules packages.
Modules must compliant FoxAPImk2.
Modules will be unpacked automatically while startup procedure.

View File

@ -2,7 +2,7 @@
RewriteEngine On RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f RewriteCond %{REQUEST_FILENAME} -f
RewriteRule . - [S=5] RewriteRule . - [S=6]
RewriteRule "^theme/([^/]+)/main.css" "/modules/$1/theme/main.css" [L] RewriteRule "^theme/([^/]+)/main.css" "/modules/$1/theme/main.css" [L]
RewriteRule "^theme/([^/]+)/img/([0-9a-zA-Z\.\-\_]*)" "/modules/$1/theme/img/$2" [L] RewriteRule "^theme/([^/]+)/img/([0-9a-zA-Z\.\-\_]*)" "/modules/$1/theme/img/$2" [L]
@ -10,3 +10,4 @@ RewriteRule "^theme/([^/]+)/font/([0-9a-zA-Z\.\-\_]*)" "/modules/$1/theme/font/$
RewriteRule "^theme/([^/]+)/css/([0-9a-zA-Z\.\-\_]*\.css)" "/modules/$1/theme/css/$2" [L] RewriteRule "^theme/([^/]+)/css/([0-9a-zA-Z\.\-\_]*\.css)" "/modules/$1/theme/css/$2" [L]
RewriteRule "^js/([^/]+)/([0-9a-zA-Z\.\-\_]*\.js)" "/modules/$1/js/$2" [L] RewriteRule "^js/([^/]+)/([0-9a-zA-Z\.\-\_]*\.js)" "/modules/$1/js/$2" [L]
RewriteRule "^css/([^/]+)/([0-9a-zA-Z\.\-\_]*\.css)" "/modules/$1/css/$2" [L]

View File

@ -106,7 +106,7 @@ function moduleInstall_Click(el) {
UI.createDialog( UI.createDialog(
UI.addFieldGroup([ UI.addFieldGroup([
UI.addField({item: "mod_name", title: langPack.core.iface.title, type: "input", reqx: "true", reqx: "true", regx: "^[A-Za-z0-9_-]*$", val: $(el.target).closest("tr").attr("modName")}), UI.addField({item: "mod_name", title: langPack.core.iface.title, type: "input", reqx: "true", regx: "^[A-Za-z0-9_-]*$", val: $(el.target).closest("tr").attr("modName")}),
UI.addField({item: "mod_priority", title: langPack.core.iface.modules.priority, type: "input", reqx: "true", regx: "^[0-9]*$", val: 100}), UI.addField({item: "mod_priority", title: langPack.core.iface.modules.priority, type: "input", reqx: "true", regx: "^[0-9]*$", val: 100}),
]), ]),
langPack.core.iface.dialodAddButton, langPack.core.iface.dialodAddButton,

View File

@ -3,6 +3,7 @@ export var langItem={
modName: "core", modName: "core",
err0: "Ошибка загрузки данных", err0: "Ошибка загрузки данных",
err1: "Ошибка", err1: "Ошибка",
emptyTableText: "Здесь ничего нет. Совсем ничего. Если это ошибка - попробуйте добавить вручную.",
errReqx: "Обязательное поле", errReqx: "Обязательное поле",
errRegx: "Несовпадение формата", errRegx: "Несовпадение формата",
ok0: "Операция завершена успешно", ok0: "Операция завершена успешно",
@ -34,7 +35,6 @@ export var langItem={
add: "Добавить", add: "Добавить",
open: "Открыть", open: "Открыть",
dialodAddButton: "Добавить", dialodAddButton: "Добавить",
dialodDelButton: "Удалить",
dialodCreateButton: "Создать", dialodCreateButton: "Создать",
dialodInfoTitle: "Информация", dialodInfoTitle: "Информация",
dialogRegisterButton: "Регистрация", dialogRegisterButton: "Регистрация",
@ -109,7 +109,6 @@ export var langItem={
allTitle: "Пользователи", allTitle: "Пользователи",
regCode: "Код регистрации", regCode: "Код регистрации",
invitesTitle: "Приглашения", invitesTitle: "Приглашения",
regCode: "Код приглашения",
inviteButtonTitle: "Пригласить", inviteButtonTitle: "Пригласить",
allowMultiUseTitle: "Разрешить множественное использование", allowMultiUseTitle: "Разрешить множественное использование",
allowMultiUseQTitle: "Множеств.", allowMultiUseQTitle: "Множеств.",

View File

@ -79,7 +79,11 @@ export function boot(xlite) {
} }
export function smartClick(ref) { export function smartClick(ref) {
if(typeof(ref)=="string") {
UI.setLocation(ref);
} else {
UI.setLocation($(ref.currentTarget).prop("href")); UI.setLocation($(ref.currentTarget).prop("href"));
}
boot(true); boot(true);
return false; return false;
} }

View File

@ -13,7 +13,7 @@ var codes={
}; };
export function showError(code, message) { export function showError(code, message) {
if (message==undefined) { message=codes[code]}; if (message==undefined) { message=codes[code]}
if (message==undefined) { message="Internal server error"} if (message==undefined) { message="Internal server error"}
$("<div>", { class: "error blanker bggray"}).appendTo("body"); $("<div>", { class: "error blanker bggray"}).appendTo("body");
$("<div>", { class: "error error_banner",html: "ERROR "+code+"<br/>"+message}).appendTo("body"); $("<div>", { class: "error error_banner",html: "ERROR "+code+"<br/>"+message}).appendTo("body");
@ -28,9 +28,9 @@ export function click (ref) {
} }
export function addButton(id, icon, title, color, onClick, cssClass, style) { export function addButton(id, icon, title, color, onClick, cssClass, style) {
var opts;
if (typeof(id)=='object') { if (typeof(id)=='object') {
var opts=id; opts=id;
id=opts.id; id=opts.id;
icon=opts.icon; icon=opts.icon;
title=opts.title; title=opts.title;
@ -191,7 +191,7 @@ export function createTabsPanel(panels,ref) {
$.each(panels,function (index,panel) { $.each(panels,function (index,panel) {
if (panel.id==undefined) {panel.id=index;} if (panel.id==undefined) {panel.id=index;}
$("<li>",{append: $("<a>",{href: "#tab-"+panel.id, text: panel.title})}) $("<li>",{append: $("<a>",{href: "#tab-"+panel.id, id: "a-tab-"+panel.id, text: panel.title})})
.appendTo("#item_tabs_ul_list"); .appendTo("#item_tabs_ul_list");
$("<div>", { $("<div>", {
id: "tab-"+panel.id, id: "tab-"+panel.id,
@ -262,12 +262,13 @@ export function addField(ref)//title, item, blockstyle, fieldstyle, type, args,
let item_id=ref.item; let item_id=ref.item;
let args = ref.args; let args = ref.args;
if (ref.args==undefined) { if (ref.args==undefined && ref.val != undefined) {
args = ref.val; args = ref.val;
} else {
args={};
} }
switch(type) { switch(type) {
case 'password': case 'password':
item = $("<input>", {class: "i", id: ref.item, name: name, type:'password',width: 'calc(100% - 44px)'}) item = $("<input>", {class: "i", id: ref.item, name: name, type:'password',width: 'calc(100% - 44px)'})
.add($("<div>",{class: "button short", style: "width: 25px; margin-right: 0; margin-left: 2; padding: 0; padding-top: 1; font-size: 13px;",append: $("<i>",{class: 'far fa-eye'}) .add($("<div>",{class: "button short", style: "width: 25px; margin-right: 0; margin-left: 2; padding: 0; padding-top: 1; font-size: 13px;",append: $("<i>",{class: 'far fa-eye'})
}) })
@ -282,6 +283,13 @@ export function addField(ref)//title, item, blockstyle, fieldstyle, type, args,
})); }));
break break
case 'passwordNew': case 'passwordNew':
if (args.chars==undefined) {
switch(args.type) {
case "num":
args.chars="0123456789";
}
}
item = $("<input>", {class: "i", id: ref.item, name: name, width: 'calc(100% - 44px)'}) item = $("<input>", {class: "i", id: ref.item, name: name, width: 'calc(100% - 44px)'})
.add($("<div>",{ .add($("<div>",{
class: "button short", class: "button short",
@ -292,7 +300,7 @@ export function addField(ref)//title, item, blockstyle, fieldstyle, type, args,
if ($("#"+item_id).prop("disabled")) { if ($("#"+item_id).prop("disabled")) {
return; return;
} }
let password=genPassword(); let password=genPassword(args.chars, args.length);
$("#"+item_id).val(password); $("#"+item_id).val(password);
$("#"+item_id).change(); $("#"+item_id).change();
if (typeof(ref.newPasswdGenCallback)=="function") { if (typeof(ref.newPasswdGenCallback)=="function") {
@ -594,6 +602,16 @@ export function collectForm(formid, getall, withIDS, withREF, validate)
} catch { } catch {
} }
data.getVals=function() {
let rv={};
$.each(data,function(idx,val) {
if (typeof(val) =='object') {
rv[idx]=val.val;
}
});
return rv;
}
return data; return data;
} }
@ -661,8 +679,8 @@ export function on_valChanged(t_this) {
export function progressBar_init() export function progressBar_init()
{ {
$('.progressbar').each(function() { $('.progressbar').each(function() {
el = $(this); let el = $(this);
val = parseInt(el.attr('value')); let val = parseInt(el.attr('value'));
el.progressbar({ el.progressbar({
value: 0 value: 0
@ -990,7 +1008,7 @@ Number.prototype.pad = function(size) {
} }
if (mode=='getPage') { if (mode=='getPage') {
return sessionStorage.getItem($(this).prop('foxPager_prefix')+"pager");c return sessionStorage.getItem($(this).prop('foxPager_prefix')+"pager");
} }
this.each(function(rid,ref) { this.each(function(rid,ref) {
@ -1070,7 +1088,7 @@ Number.prototype.pad = function(size) {
}).appendTo(ref); }).appendTo(ref);
} else if (mode=='update') { } else if (mode=='update') {
prefix = $(ref).prop("foxPager_prefix"); let prefix = $(ref).prop("foxPager_prefix");
sessionStorage.setItem(prefix+"pager", options.page); sessionStorage.setItem(prefix+"pager", options.page);
$(ref).prop('foxPager_page',options.page); $(ref).prop('foxPager_page',options.page);
$(ref).prop('foxPager_pages',options.pages); $(ref).prop('foxPager_pages',options.pages);

View File

@ -37,7 +37,6 @@ function doValidation(code) {
code: code, code: code,
}, },
method: "core/user/validateEMailCode", method: "core/user/validateEMailCode",
errDict: langPack.core.iface.users.errors,
onSuccess: function(json) { onSuccess: function(json) {
UI.closeDialog('addgrp'); UI.closeDialog('addgrp');

View File

@ -78,7 +78,7 @@ a.ui-button,
a:link.ui-button, a:link.ui-button,
a:visited.ui-button, a:visited.ui-button,
.ui-button { .ui-button {
color: #aaaaa; color: #aaaaaa;
text-decoration: none; text-decoration: none;
} }
.ui-state-hover, .ui-state-hover,

View File

@ -243,7 +243,6 @@ div.header_user
border: 2px solid red; border: 2px solid red;
background-color: rgba(0, 0, 0, 0.85); background-color: rgba(0, 0, 0, 0.85);
margin: 0;
padding: 70px 0 0 0; padding: 70px 0 0 0;
position: absolute; position: absolute;
left: calc(50% - 250px); left: calc(50% - 250px);
@ -254,7 +253,9 @@ div.header_user
height: 150px; height: 150px;
font-family: 'Fira Mono', monospace; font-family: 'Fira Mono', monospace;
font-weight: 200; font-weight: 200;
font-size: 32px; color: #FF3500; margin: 1%; font-size: 32px;
color: #FF3500;
margin: 1%;
z-index: 200; z-index: 200;
} }
@ -403,7 +404,6 @@ div.t_navy_main, div.t_main
{ {
text-align: left; text-align: left;
vertical-align: top; vertical-align: top;
padding-top: 0px;
padding: 10px 7px 10px 7px; padding: 10px 7px 10px 7px;
} }
@ -674,7 +674,7 @@ li.xmenu {
margin-left: 14px; margin-left: 14px;
} }
t_navy_main .xmenu p { .xmenu p {
margin-left: 5px; margin-left: 5px;
} }
@ -1437,7 +1437,6 @@ div.alert, p.alert
top: 50%; top: 50%;
margin-left: -350px; margin-left: -350px;
margin-top: -25px; margin-top: -25px;
font-weight: bold;
vertical-align: middle; vertical-align: middle;
padding-top: 10px; padding-top: 10px;
color: white; color: white;
@ -1590,7 +1589,6 @@ div.chevron.first .button
div.login div.login
{ {
width: 300px;
position: absolute; position: absolute;
left: 50%; left: 50%;
top: 50%; top: 50%;
@ -1672,7 +1670,7 @@ div.dialog textarea
table.datatable td.code table.datatable td.code
{ {
font-family: 'Share Tech Mono'; font-family: Share Tech Mono, sans-serif;
font-size: 16px; font-size: 16px;
color: rgba(255,255,255,0.8); color: rgba(255,255,255,0.8);
} }
@ -1743,7 +1741,6 @@ div.accordion .ui-accordion-header.ui-state-active {
/* accordion and tabs */ /* accordion and tabs */
div.accordion .ui-accordion-header { div.accordion .ui-accordion-header {
border-radius: 5px;
background-color: rgba(var(--mxs-bg-rgba-prefix),0.7); background-color: rgba(var(--mxs-bg-rgba-prefix),0.7);
font-family: 'Fira Sans Extra Condensed', sans-serif; font-family: 'Fira Sans Extra Condensed', sans-serif;
font-weight: normal; font-weight: normal;