From a0b935c08279c82c5f3483f2add9b578aa008d92 Mon Sep 17 00:00:00 2001 From: Roman Hergenreder Date: Thu, 25 Jun 2020 16:54:58 +0200 Subject: [PATCH] Bugfixes, Postgres improved support --- core/Api/RoutesAPI.class.php | 6 +- core/Api/SendMail.class.php | 33 +++++- core/Api/SettingsAPI.class.php | 112 ++++++++++++++++++++ core/Api/Stats.class.php | 41 ++++--- core/Configuration/.gitignore | 2 - core/Configuration/Configuration.class.php | 48 +++------ core/Configuration/CreateDatabase.class.php | 29 ++++- core/Configuration/KeyData.class.php | 17 --- core/Configuration/Settings.class.php | 71 +++++++++++++ core/Documents/Install.class.php | 70 +++++++----- core/Driver/SQL/MySQL.class.php | 2 +- core/Driver/SQL/PostgreSQL.class.php | 2 +- core/Driver/SQL/SQL.class.php | 8 +- core/Elements/View.class.php | 2 +- core/Objects/Session.class.php | 12 +-- core/Objects/User.class.php | 12 ++- index.php | 4 +- js/admin.min.js | 2 +- src/src/views/addgroup.js | 2 +- 19 files changed, 350 insertions(+), 125 deletions(-) create mode 100644 core/Api/SettingsAPI.class.php delete mode 100755 core/Configuration/KeyData.class.php create mode 100644 core/Configuration/Settings.class.php diff --git a/core/Api/RoutesAPI.class.php b/core/Api/RoutesAPI.class.php index 8be140f..793ba2a 100644 --- a/core/Api/RoutesAPI.class.php +++ b/core/Api/RoutesAPI.class.php @@ -62,7 +62,7 @@ namespace Api\Routes { "action" => $row["action"], "target" => $row["target"], "extra" => $row["extra"] ?? "", - "active" => intval($row["active"]), + "active" => intval($sql->parseBool($row["active"])), ); } @@ -147,7 +147,6 @@ namespace Api\Routes { return false; } - $sql = $this->user->getSQL(); // DELETE old rules @@ -190,7 +189,7 @@ namespace Api\Routes { $value = $route[$key]; $type = Parameter::parseType($value); - if ($type !== $expectedType && ($key !== "active" || !is_null($value))) { + if ($type !== $expectedType) { $expectedTypeName = Parameter::names[$expectedType]; $gotTypeName = Parameter::names[$type]; return $this->createError("Route $index has invalid value for key: $key, expected: $expectedTypeName, got: $gotTypeName"); @@ -218,6 +217,5 @@ namespace Api\Routes { return true; } } - } diff --git a/core/Api/SendMail.class.php b/core/Api/SendMail.class.php index 6151600..6603460 100644 --- a/core/Api/SendMail.class.php +++ b/core/Api/SendMail.class.php @@ -5,6 +5,7 @@ use Api\Parameter\Parameter; use Api\Parameter\StringType; use External\PHPMailer\Exception; use External\PHPMailer\PHPMailer; +use Objects\ConnectionData; class SendMail extends Request { @@ -20,17 +21,39 @@ class SendMail extends Request { $this->isPublic = false; } + private function getMailConfig() : ?ConnectionData { + $req = new \Api\Settings\Get($this->user); + $this->success = $req->execute(array("key" => "^mail_")); + $this->lastError = $req->getLastError(); + + if ($this->success) { + $settings = $req->getResult()["settings"]; + if (!isset($settings["mail_enabled"]) || $settings["mail_enabled"] !== "1") { + $this->createError("Mail is not configured yet."); + return null; + } + + $host = $settings["mail_host"] ?? "localhost"; + $port = intval($settings["mail_port"] ?? "25"); + $login = $settings["mail_username"] ?? ""; + $password = $settings["mail_password"] ?? ""; + return new ConnectionData($host, $port, $login, $password); + } + + return null; + } + public function execute($values = array()) { if(!parent::execute($values)) { return false; } - try { - $mailConfig = $this->user->getConfiguration()->getMail(); - if (!$mailConfig) { - return $this->createError("Mail is not configured yet."); - } + $mailConfig = $this->getMailConfig(); + if (!$this->success) { + return false; + } + try { $mail = new PHPMailer; $mail->IsSMTP(); $mail->setFrom($this->getParam('from'), $this->getParam('fromName')); diff --git a/core/Api/SettingsAPI.class.php b/core/Api/SettingsAPI.class.php new file mode 100644 index 0000000..aec227c --- /dev/null +++ b/core/Api/SettingsAPI.class.php @@ -0,0 +1,112 @@ + new StringType('key', 32, true, NULL) + )); + + $this->requiredGroup = array(USER_GROUP_ADMIN); + $this->loginRequired = true; + } + + public function execute($values = array()) { + if(!parent::execute($values)) { + return false; + } + + $key = $this->getParam("key"); + $sql = $this->user->getSQL(); + + $query = $sql->select("name", "value") ->from("Settings"); + + if (!is_null($key) && !empty($key)) { + $query->where(new CondRegex($key, new Column("name"))); + } + + $res = $query->execute(); + + $this->success = ($res !== FALSE); + $this->lastError = $sql->getLastError(); + + if ($this->success) { + $settings = array(); + foreach($res as $row) { + $settings[$row["name"]] = $row["value"]; + } + $this->result["settings"] = $settings; + } + + return $this->success; + } + } + + class Set extends SettingsAPI { + public function __construct(User $user, bool $externalCall = false) { + parent::__construct($user, $externalCall, array( + 'settings' => new Parameter('settings', Parameter::TYPE_ARRAY) + )); + + $this->requiredGroup = array(USER_GROUP_ADMIN); + $this->loginRequired = true; + } + + public function execute($values = array()) { + if (!parent::execute($values)) { + return false; + } + + $values = $this->getParam("settings"); + if (empty($values)) { + return $this->createError("No values given."); + } + + $paramKey = new StringType('key', 32); + $paramValue = new StringType('value', 1024); + + $sql = $this->user->getSQL(); + $query = $sql->insert("Settings", array("name", "value")); + + foreach($values as $key => $value) { + if (!$paramKey->parseParam($key)) { + $key = print_r($key, true); + return $this->createError("Invalid Type for key in parameter settings: '$key' (Required: " . $paramKey->getTypeName() . ")"); + } else if(!$paramValue->parseParam($value)) { + $value = print_r($value, true); + return $this->createError("Invalid Type for value in parameter settings: '$value' (Required: " . $paramValue->getTypeName() . ")"); + } else { + $query->addRow($paramKey->value, $paramValue->value); + } + } + + $query->onDuplicateKeyStrategy(new UpdateStrategy( + array("name"), + array("value" => new Column("value"))) + ); + + $this->success = ($query->execute() !== FALSE); + $this->lastError = $sql->getLastError(); + return $this->success; + } + } +} \ No newline at end of file diff --git a/core/Api/Stats.class.php b/core/Api/Stats.class.php index 3bb1f3e..5628aa7 100644 --- a/core/Api/Stats.class.php +++ b/core/Api/Stats.class.php @@ -67,6 +67,17 @@ class Stats extends Request { return $visitors; } + private function isMailConfigured() { + $req = new \Api\Settings\Get($this->user); + $this->success = $req->execute(array("key" => "^mail_enabled$")); + + if ($this->success) { + return ($req->getResult()["mail_enabled"] ?? "0") === "1"; + } + + return $this->success; + } + public function execute($values = array()) { if(!parent::execute($values)) { return false; @@ -75,26 +86,32 @@ class Stats extends Request { $userCount = $this->getUserCount(); $pageCount = $this->getPageCount(); $visitorStatistics = $this->getVisitorStatistics(); + if (!$this->success) { + return false; + } $loadAvg = "Unknown"; if (function_exists("sys_getloadavg")) { $loadAvg = sys_getloadavg(); } - if ($this->success) { - $this->result["userCount"] = $userCount; - $this->result["pageCount"] = $pageCount; - $this->result["visitors"] = $visitorStatistics; - $this->result["server"] = array( - "version" => WEBBASE_VERSION, - "server" => $_SERVER["SERVER_SOFTWARE"] ?? "Unknown", - "memory_usage" => memory_get_usage(), - "load_avg" => $loadAvg, - "database" => $this->user->getSQL()->getStatus(), - "mail" => $this->user->getConfiguration()->getMail() !== NULL - ); + $mailConfigured = $this->isMailConfigured(); + if (!$this->success) { + return false; } + $this->result["userCount"] = $userCount; + $this->result["pageCount"] = $pageCount; + $this->result["visitors"] = $visitorStatistics; + $this->result["server"] = array( + "version" => WEBBASE_VERSION, + "server" => $_SERVER["SERVER_SOFTWARE"] ?? "Unknown", + "memory_usage" => memory_get_usage(), + "load_avg" => $loadAvg, + "database" => $this->user->getSQL()->getStatus(), + "mail" => $mailConfigured + ); + return $this->success; } diff --git a/core/Configuration/.gitignore b/core/Configuration/.gitignore index 6b0cf63..bd1b2f7 100755 --- a/core/Configuration/.gitignore +++ b/core/Configuration/.gitignore @@ -1,3 +1 @@ -Mail\.class\.php -JWT\.class\.php Database\.class\.php diff --git a/core/Configuration/Configuration.class.php b/core/Configuration/Configuration.class.php index 8c7a009..6230d75 100755 --- a/core/Configuration/Configuration.class.php +++ b/core/Configuration/Configuration.class.php @@ -2,53 +2,33 @@ namespace Configuration; -use Error; use Objects\ConnectionData; class Configuration { private ?ConnectionData $database; - private ?ConnectionData $mail; - private ?KeyData $jwt; + private Settings $settings; function __construct() { - } + $this->database = null; + $this->settings = Settings::loadDefaults(); - public function load() { - try { - - $classes = array( - \Configuration\Database::class => &$this->database, - \Configuration\Mail::class => &$this->mail, - \Configuration\JWT::class => &$this->jwt - ); - - $success = true; - foreach($classes as $class => &$ref) { - $path = getClassPath($class); - if(!file_exists($path)) { - $success = false; - } else { - include_once $path; - if(class_exists($class)) { - $ref = new $class(); - } - } + $class = \Configuration\Database::class; + $path = getClassPath($class, true); + if(file_exists($path) && is_readable($path)) { + include_once $path; + if(class_exists($class)) { + $this->database = new \Configuration\Database(); } - - return $success; - } catch(Error $e) { - die($e); } } - public function getDatabase() { return $this->database; } - public function getJWT() { return $this->jwt; } - public function getMail() { return $this->mail; } + public function getDatabase() : ?ConnectionData { + return $this->database; + } - public function isFilePresent($className) { - $path = getClassPath("\\Configuration\\$className"); - return file_exists($path); + public function getSettings() : Settings { + return $this->settings; } public function create(string $className, $data) { diff --git a/core/Configuration/CreateDatabase.class.php b/core/Configuration/CreateDatabase.class.php index f64b4cf..04dae04 100755 --- a/core/Configuration/CreateDatabase.class.php +++ b/core/Configuration/CreateDatabase.class.php @@ -8,6 +8,9 @@ use \Driver\SQL\Strategy\CascadeStrategy; class CreateDatabase { + // NOTE: + // explicit serial ids removed due to postgres' serial implementation + public static function createQueries(SQL $sql) { $queries = array(); @@ -21,8 +24,8 @@ class CreateDatabase { ->unique("name"); $queries[] = $sql->insert("Language", array("uid", "code", "name")) - ->addRow(1, "en_US", 'American English') - ->addRow(2, "de_DE", 'Deutsch Standard'); + ->addRow( "en_US", 'American English') + ->addRow( "de_DE", 'Deutsch Standard'); $queries[] = $sql->createTable("User") ->addSerial("uid") @@ -72,9 +75,9 @@ class CreateDatabase { ->unique("name"); $queries[] = $sql->insert("Group", array("uid", "name", "color")) - ->addRow(USER_GROUP_MODERATOR, USER_GROUP_MODERATOR_NAME, "#007bff") - ->addRow(USER_GROUP_SUPPORT, USER_GROUP_SUPPORT_NAME, "#28a745") - ->addRow(USER_GROUP_ADMIN, USER_GROUP_ADMIN_NAME, "#dc3545"); + ->addRow(USER_GROUP_MODERATOR_NAME, "#007bff") + ->addRow(USER_GROUP_SUPPORT_NAME, "#28a745") + ->addRow(USER_GROUP_ADMIN_NAME, "#dc3545"); $queries[] = $sql->createTable("UserGroup") ->addInt("user_id") @@ -137,6 +140,22 @@ class CreateDatabase { ->addRow("^/acceptInvite(/)?$", "dynamic", "\\Documents\\Account", "\\Views\\Account\\AcceptInvite") ->addRow("^/$", "static", "/static/welcome.html", NULL); + $queries[] = $sql->createTable("Settings") + ->addString("name", 32) + ->addString("value", 1024, true) + ->primaryKey("name"); + + $settingsQuery = $sql->insert("Settings", array("name", "value")) + // ->addRow("mail_enabled", "0") # this key will be set during installation + ->addRow("mail_host", "") + ->addRow("mail_port", "") + ->addRow("mail_username", "") + ->addRow("mail_password", "") + ->addRow("mail_from", ""); + + (Settings::loadDefaults())->addRows($settingsQuery); + $queries[] = $settingsQuery; + return $queries; } } diff --git a/core/Configuration/KeyData.class.php b/core/Configuration/KeyData.class.php deleted file mode 100755 index 68e2122..0000000 --- a/core/Configuration/KeyData.class.php +++ /dev/null @@ -1,17 +0,0 @@ -key = $key; - } - - public function getKey() { - return $this->key; - } - -} \ No newline at end of file diff --git a/core/Configuration/Settings.class.php b/core/Configuration/Settings.class.php new file mode 100644 index 0000000..2a83734 --- /dev/null +++ b/core/Configuration/Settings.class.php @@ -0,0 +1,71 @@ +jwtSecret; + } + + public function isInstalled() { + return $this->installationComplete; + } + + public static function loadDefaults() : Settings { + $hostname = php_uname("n"); + $protocol = getProtocol(); + $jwt = generateRandomString(32); + + $settings = new Settings(); + $settings->siteName = "WebBase"; + $settings->baseUrl = "$protocol://$hostname"; + $settings->jwtSecret = $jwt; + $settings->installationComplete = false; + $settings->registrationAllowed = false; + return $settings; + } + + public function loadFromDatabase(User $user) { + $req = new \Api\Settings\Get($user); + $success = $req->execute(); + + if ($success) { + $result = $req->getResult()["settings"]; + $this->siteName = $result["site_name"] ?? $this->siteName; + $this->registrationAllowed = $result["user_registration_enabled"] ?? $this->registrationAllowed; + $this->installationComplete = $result["installation_completed"] ?? $this->installationComplete; + $this->jwtSecret = $result["jwt_secret"] ?? $this->jwtSecret; + + if (!isset($result["jwt_secret"])) { + $req = new \Api\Settings\Set($user); + $req->execute(array("settings" => array( + "jwt_secret" => $this->jwtSecret + ))); + } + } + + return false; + } + + public function addRows(Insert $query) { + $query->addRow("site_name", $this->siteName) + ->addRow("base_url", $this->baseUrl) + ->addRow("user_registration_enabled", $this->registrationAllowed ? "1" : "0") + ->addRow("installation_completed", $this->installationComplete ? "1" : "0") + ->addRow("jwt_secret", $this->jwtSecret); + } +} \ No newline at end of file diff --git a/core/Documents/Install.class.php b/core/Documents/Install.class.php index 5d43785..b7daf7c 100644 --- a/core/Documents/Install.class.php +++ b/core/Documents/Install.class.php @@ -16,8 +16,6 @@ namespace Documents { namespace Documents\Install { - use Api\Notifications\Create; - use Api\Parameter\Parameter; use Configuration\CreateDatabase; use Driver\SQL\SQL; use Elements\Body; @@ -113,6 +111,10 @@ namespace Documents\Install { } $sql = $user->getSQL(); + if(!$sql || !$sql->isConnected()) { + return self::DATABASE_CONFIGURATION; + } + $countKeyword = $sql->count(); $res = $sql->select($countKeyword)->from("User")->execute(); if ($res === FALSE) { @@ -125,19 +127,28 @@ namespace Documents\Install { } } - if($step === self::ADD_MAIL_SERVICE && $config->isFilePresent("Mail")) { - $step = self::FINISH_INSTALLATION; - if(!$config->isFilePresent("JWT") && !$config->create("JWT", generateRandomString(32))) { - $this->errorString = "Unable to create jwt file"; - } else { - $req = new Create($user); - $success = $req->execute(array( - "title" => "Welcome", - "message" => "Your Web-base was successfully installed. Check out the admin dashboard. Have fun!", - "groupId" => USER_GROUP_ADMIN) - ); + if ($step === self::ADD_MAIL_SERVICE) { + $req = new \Api\Settings\Get($user); + $success = $req->execute(array("key" => "^mail_enabled$")); + if (!$success) { + $this->errorString = $req->getLastError(); + return self::DATABASE_CONFIGURATION; + } else if (isset($req->getResult()["settings"]["mail_enabled"])) { + $step = self::FINISH_INSTALLATION; + + $req = new \Api\Settings\Set($user); + $success = $req->execute(array("settings" => array("installation_completed" => "1"))); if (!$success) { $this->errorString = $req->getLastError(); + } else { + $req = new \Api\Notifications\Create($user); + $success = $req->execute(array( + "title" => "Welcome", + "message" => "Your Web-base was successfully installed. Check out the admin dashboard. Have fun!", + "groupId" => USER_GROUP_ADMIN + ) + ); + $this->errorString = $req->getLastError(); } } } @@ -264,7 +275,8 @@ namespace Documents\Install { } } - if($success && !$this->getDocument()->getUser()->getConfiguration()->create("Database", $connectionData)) { + $config = $this->getDocument()->getUser()->getConfiguration(); + if(!$config->create("Database", $connectionData)) { $success = false; $msg = "Unable to write file"; } @@ -348,10 +360,9 @@ namespace Documents\Install { $success = true; $msg = $this->errorString; if($this->getParameter("skip") === "true") { - if(!$user->getConfiguration()->create("Mail", null)) { - $success = false; - $msg = "Unable to create file"; - } + $req = new \Api\Settings\Set($user); + $success = $req->execute(array("settings" => array( "mail_enabled" => "0" ))); + $msg = $req->getLastError(); } else { $address = $this->getParameter("address"); @@ -415,11 +426,15 @@ namespace Documents\Install { } if($success) { - $connectionData = new ConnectionData($address, $port, $username, $password); - if(!$user->getConfiguration()->create("Mail", $connectionData)) { - $success = false; - $msg = "Unable to create file"; - } + $req = new \Api\Settings\Set($user); + $success = $req->execute(array("settings" => array( + "mail_enabled" => "1", + "mail_host" => "$address", + "mail_port" => "$port", + "mail_username" => "$username", + "mail_password" => "$password", + ))); + $msg = $req->getLastError(); } } } @@ -461,26 +476,26 @@ namespace Documents\Install { switch($status) { case self::PENDING: - $statusIcon = ''; + $statusIcon = $this->createIcon("spinner"); $statusText = "Loading…"; $statusColor = "muted"; break; case self::SUCCESSFUL: - $statusIcon = ''; + $statusIcon = $this->createIcon("check-circle"); $statusText = "Successful"; $statusColor = "success"; break; case self::ERROR: - $statusIcon = ''; + $statusIcon = $this->createIcon("times-circle"); $statusText = "Failed"; $statusColor = "danger"; break; case self::NOT_STARTED: default: - $statusIcon = ''; + $statusIcon = $this->createIcon("circle", "far"); $statusText = "Pending"; $statusColor = "muted"; break; @@ -797,6 +812,5 @@ namespace Documents\Install { return $html; } - } } diff --git a/core/Driver/SQL/MySQL.class.php b/core/Driver/SQL/MySQL.class.php index 0f418e1..2a5fc26 100644 --- a/core/Driver/SQL/MySQL.class.php +++ b/core/Driver/SQL/MySQL.class.php @@ -173,7 +173,7 @@ class MySQL extends SQL { $leftColumn = $this->columnName($key); if ($value instanceof Column) { $columnName = $this->columnName($value->getName()); - $updateValues[] = "$leftColumn=$columnName"; + $updateValues[] = "$leftColumn=VALUES($columnName)"; } else if($value instanceof Add) { $columnName = $this->columnName($value->getColumn()); $operator = $value->getOperator(); diff --git a/core/Driver/SQL/PostgreSQL.class.php b/core/Driver/SQL/PostgreSQL.class.php index 0f5895d..f8fe8bc 100644 --- a/core/Driver/SQL/PostgreSQL.class.php +++ b/core/Driver/SQL/PostgreSQL.class.php @@ -139,7 +139,7 @@ class PostgreSQL extends SQL { $leftColumn = $this->columnName($key); if ($value instanceof Column) { $columnName = $this->columnName($value->getName()); - $updateValues[] = "$leftColumn=$columnName"; + $updateValues[] = "$leftColumn=EXCLUDED.$columnName"; } else if ($value instanceof Add) { $columnName = $this->columnName($value->getColumn()); $operator = $value->getOperator(); diff --git a/core/Driver/SQL/SQL.class.php b/core/Driver/SQL/SQL.class.php index ac86739..3c5b094 100644 --- a/core/Driver/SQL/SQL.class.php +++ b/core/Driver/SQL/SQL.class.php @@ -215,7 +215,9 @@ abstract class SQL { } public function executeTruncate(Truncate $truncate) { - return $this->execute("TRUNCATE " . $truncate->getTable()); + $query = "TRUNCATE " . $this->tableName($truncate->getTable()); + if ($truncate->dump) { var_dump($query); } + return $this->execute($query); } public function executeUpdate(Update $update) { @@ -391,4 +393,8 @@ abstract class SQL { } public abstract function getStatus(); + + public function parseBool($val) : bool { + return in_array($val, array(true, 1, '1', 't', 'true', 'TRUE')); + } } \ No newline at end of file diff --git a/core/Elements/View.class.php b/core/Elements/View.class.php index 873c458..71954c8 100644 --- a/core/Elements/View.class.php +++ b/core/Elements/View.class.php @@ -94,7 +94,7 @@ abstract class View extends StaticView { protected function createIcon($icon, $type = "fas", $classes = "") { $iconClass = "$type fa-$icon"; - if($icon === "spinner") + if($icon === "spinner" || $icon === "circle-notch") $iconClass .= " fa-spin"; if($classes) diff --git a/core/Objects/Session.class.php b/core/Objects/Session.class.php index cb0d749..e3e9d35 100644 --- a/core/Objects/Session.class.php +++ b/core/Objects/Session.class.php @@ -62,13 +62,11 @@ class Session extends ApiObject { public function sendCookie() { $this->updateMetaData(); - $jwt = $this->user->getConfiguration()->getJwt(); - if($jwt) { - $token = array('userId' => $this->user->getId(), 'sessionId' => $this->sessionId); - $sessionCookie = JWT::encode($token, $jwt->getKey()); - $secure = strcmp(getProtocol(), "https") === 0; - setcookie('session', $sessionCookie, $this->getExpiresTime(), "/", "", $secure); - } + $settings = $this->user->getConfiguration()->getSettings(); + $token = array('userId' => $this->user->getId(), 'sessionId' => $this->sessionId); + $sessionCookie = JWT::encode($token, $settings->getJwtSecret()); + $secure = strcmp(getProtocol(), "https") === 0; + setcookie('session', $sessionCookie, $this->getExpiresTime(), "/", "", $secure); } public function getExpiresTime() { diff --git a/core/Objects/User.class.php b/core/Objects/User.class.php index ec7d05d..a293ba6 100644 --- a/core/Objects/User.class.php +++ b/core/Objects/User.class.php @@ -43,6 +43,10 @@ class User extends ApiObject { $databaseConf = $this->configuration->getDatabase(); if($databaseConf) { $this->sql = SQL::createConnection($databaseConf); + if ($this->sql->isConnected()) { + $settings = $this->configuration->getSettings(); + $settings->loadFromDatabase($this); + } } else { $this->sql = null; } @@ -155,7 +159,7 @@ class User extends ApiObject { $this->uid = $userId; $this->session = new Session($this, $sessionId, $csrfToken); $this->session->setData(json_decode($row["data"] ?? '{}')); - $this->session->stayLoggedIn($row["stay_logged_in"]); + $this->session->stayLoggedIn($this->sql->parseBool(["stay_logged_in"])); if($sessionUpdate) $this->session->update(); $this->loggedIn = true; @@ -175,11 +179,11 @@ class User extends ApiObject { private function parseCookies() { if(isset($_COOKIE['session']) && is_string($_COOKIE['session']) - && !empty($_COOKIE['session']) - && ($jwt = $this->configuration->getJWT())) { + && !empty($_COOKIE['session'])) { try { $token = $_COOKIE['session']; - $decoded = (array)JWT::decode($token, $jwt->getKey()); + $settings = $this->configuration->getSettings(); + $decoded = (array)JWT::decode($token, $settings->getJwtSecret()); if(!is_null($decoded)) { $userId = (isset($decoded['userId']) ? $decoded['userId'] : NULL); $sessionId = (isset($decoded['sessionId']) ? $decoded['sessionId'] : NULL); diff --git a/index.php b/index.php index a3c221f..c60ea9e 100644 --- a/index.php +++ b/index.php @@ -25,8 +25,10 @@ spl_autoload_register(function($class) { }); $config = new Configuration(); -$installation = (!$config->load()); $user = new Objects\User($config); +$sql = $user->getSQL(); +$settings = $config->getSettings(); +$installation = !$sql || ($sql->isConnected() && !$settings->isInstalled()); if(isset($_GET["api"]) && is_string($_GET["api"])) { header("Content-Type: application/json"); diff --git a/js/admin.min.js b/js/admin.min.js index 9df2301..3e92cb7 100644 --- a/js/admin.min.js +++ b/js/admin.min.js @@ -9251,7 +9251,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) * /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return CreateGroup; });\n/* harmony import */ var _elements_alert__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../elements/alert */ \"./src/elements/alert.js\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/esm/react-router-dom.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _elements_icon__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../elements/icon */ \"./src/elements/icon.js\");\n/* harmony import */ var react_tooltip__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react-tooltip */ \"./node_modules/react-tooltip/dist/index.es.js\");\n/* harmony import */ var rc_color_picker_assets_index_css__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rc-color-picker/assets/index.css */ \"./node_modules/rc-color-picker/assets/index.css\");\n/* harmony import */ var rc_color_picker_assets_index_css__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(rc_color_picker_assets_index_css__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var rc_color_picker__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rc-color-picker */ \"./node_modules/rc-color-picker/lib/index.js\");\n/* harmony import */ var rc_color_picker__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(rc_color_picker__WEBPACK_IMPORTED_MODULE_6__);\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n\n\n\n\n\n\n\n\nvar CreateGroup = /*#__PURE__*/function (_React$Component) {\n _inherits(CreateGroup, _React$Component);\n\n var _super = _createSuper(CreateGroup);\n\n function CreateGroup(props) {\n var _this;\n\n _classCallCheck(this, CreateGroup);\n\n _this = _super.call(this, props);\n _this.state = {\n alerts: [],\n isSubmitting: false,\n name: \"\",\n color: \"#0F0\"\n };\n _this.parent = {\n api: props.api\n };\n return _this;\n }\n\n _createClass(CreateGroup, [{\n key: \"removeAlert\",\n value: function removeAlert(i) {\n if (i >= 0 && i < this.state.alerts.length) {\n var alerts = this.state.alerts.slice();\n alerts.splice(i, 1);\n this.setState(_objectSpread(_objectSpread({}, this.state), {}, {\n alerts: alerts\n }));\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this2 = this;\n\n var alerts = [];\n\n var _loop = function _loop(i) {\n alerts.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](_elements_alert__WEBPACK_IMPORTED_MODULE_0__[\"default\"], _extends({\n key: \"error-\" + i,\n onClose: function onClose() {\n return _this2.removeAlert(i);\n }\n }, _this2.state.alerts[i])));\n };\n\n for (var i = 0; i < this.state.alerts.length; i++) {\n _loop(i);\n }\n\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](react__WEBPACK_IMPORTED_MODULE_2__[\"Fragment\"], null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"content-header\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"container-fluid\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"row mb-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"col-sm-6\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"h1\", {\n className: \"m-0 text-dark\"\n }, \"Create a new group\")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"col-sm-6\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"ol\", {\n className: \"breadcrumb float-sm-right\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"li\", {\n className: \"breadcrumb-item\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](react_router_dom__WEBPACK_IMPORTED_MODULE_1__[\"Link\"], {\n to: \"/admin/dashboard\"\n }, \"Home\")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"li\", {\n className: \"breadcrumb-item\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](react_router_dom__WEBPACK_IMPORTED_MODULE_1__[\"Link\"], {\n to: \"/admin/users\"\n }, \"Users\")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"li\", {\n className: \"breadcrumb-item active\"\n }, \"Add User\")))))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"content\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"row\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"col-lg-6 pl-5 pr-5\"\n }, alerts, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"form\", {\n role: \"form\",\n onSubmit: function onSubmit(e) {\n return _this2.submitForm(e);\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"form-group\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"label\", {\n htmlFor: \"name\"\n }, \"Group Name\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"input\", {\n type: \"text\",\n className: \"form-control\",\n placeholder: \"Name\",\n name: \"name\",\n id: \"name\",\n maxLength: 32,\n value: this.state.name,\n onChange: this.onChangeInput.bind(this)\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"form-group\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"label\", {\n htmlFor: \"color\"\n }, \"Color\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"input-group-prepend\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"span\", {\n className: \"input-group-text\",\n style: {\n padding: \"0.35rem 0.4rem 0 0.4rem\"\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](rc_color_picker__WEBPACK_IMPORTED_MODULE_6___default.a, {\n color: this.state.color,\n alpha: 100,\n name: \"color\",\n onChange: this.onChangeColor.bind(this),\n placement: \"topLeft\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"span\", {\n className: \"rc-color-picker-trigger\"\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"input\", {\n type: \"text\",\n className: \"form-control float-right\",\n readOnly: true,\n value: this.state.color\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](react_router_dom__WEBPACK_IMPORTED_MODULE_1__[\"Link\"], {\n to: \"/admin/users\",\n className: \"btn btn-info mt-2 mr-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](_elements_icon__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n icon: \"arrow-left\"\n }), \"\\xA0Back\"), this.state.isSubmitting ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"button\", {\n type: \"submit\",\n className: \"btn btn-primary mt-2\",\n disabled: true\n }, \"Loading\\u2026\\xA0\", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](_elements_icon__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n icon: \"circle-notch\"\n })) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"button\", {\n type: \"submit\",\n className: \"btn btn-primary mt-2\"\n }, \"Submit\"))))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](react_tooltip__WEBPACK_IMPORTED_MODULE_4__[\"default\"], null));\n }\n }, {\n key: \"onChangeColor\",\n value: function onChangeColor(e) {\n this.setState(_objectSpread(_objectSpread({}, this.state), {}, {\n color: e.color\n }));\n }\n }, {\n key: \"onChangeInput\",\n value: function onChangeInput(event) {\n var target = event.target;\n var value = target.value;\n var name = target.name;\n this.setState(_objectSpread(_objectSpread({}, this.state), {}, _defineProperty({}, name, value)));\n }\n }, {\n key: \"submitForm\",\n value: function submitForm(e) {\n var _this3 = this;\n\n e.preventDefault();\n var name = this.state.name;\n var color = this.state.color;\n this.setState(_objectSpread(_objectSpread({}, this.state), {}, {\n isSubmitting: true\n }));\n this.parent.api.createGroup(name, color).then(function (res) {\n var alerts = _this3.state.alerts.slice();\n\n if (res.success) {\n alerts.push({\n message: \"Group was successfully created\",\n title: \"Success!\",\n type: \"success\"\n });\n\n _this3.setState(_objectSpread(_objectSpread({}, _this3.state), {}, {\n name: \"\",\n color: \"\",\n alerts: alerts,\n isSubmitting: false\n }));\n } else {\n alerts.push({\n message: res.msg,\n title: \"Error creating Group\",\n type: \"danger\"\n });\n\n _this3.setState(_objectSpread(_objectSpread({}, _this3.state), {}, {\n name: \"\",\n color: \"\",\n alerts: alerts,\n isSubmitting: false\n }));\n }\n });\n }\n }]);\n\n return CreateGroup;\n}(react__WEBPACK_IMPORTED_MODULE_2__[\"Component\"]);\n\n\n\n//# sourceURL=webpack:///./src/views/addgroup.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return CreateGroup; });\n/* harmony import */ var _elements_alert__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../elements/alert */ \"./src/elements/alert.js\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/esm/react-router-dom.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _elements_icon__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../elements/icon */ \"./src/elements/icon.js\");\n/* harmony import */ var react_tooltip__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react-tooltip */ \"./node_modules/react-tooltip/dist/index.es.js\");\n/* harmony import */ var rc_color_picker_assets_index_css__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rc-color-picker/assets/index.css */ \"./node_modules/rc-color-picker/assets/index.css\");\n/* harmony import */ var rc_color_picker_assets_index_css__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(rc_color_picker_assets_index_css__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var rc_color_picker__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rc-color-picker */ \"./node_modules/rc-color-picker/lib/index.js\");\n/* harmony import */ var rc_color_picker__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(rc_color_picker__WEBPACK_IMPORTED_MODULE_6__);\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n\n\n\n\n\n\n\n\nvar CreateGroup = /*#__PURE__*/function (_React$Component) {\n _inherits(CreateGroup, _React$Component);\n\n var _super = _createSuper(CreateGroup);\n\n function CreateGroup(props) {\n var _this;\n\n _classCallCheck(this, CreateGroup);\n\n _this = _super.call(this, props);\n _this.state = {\n alerts: [],\n isSubmitting: false,\n name: \"\",\n color: \"#0F0\"\n };\n _this.parent = {\n api: props.api\n };\n return _this;\n }\n\n _createClass(CreateGroup, [{\n key: \"removeAlert\",\n value: function removeAlert(i) {\n if (i >= 0 && i < this.state.alerts.length) {\n var alerts = this.state.alerts.slice();\n alerts.splice(i, 1);\n this.setState(_objectSpread(_objectSpread({}, this.state), {}, {\n alerts: alerts\n }));\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this2 = this;\n\n var alerts = [];\n\n var _loop = function _loop(i) {\n alerts.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](_elements_alert__WEBPACK_IMPORTED_MODULE_0__[\"default\"], _extends({\n key: \"error-\" + i,\n onClose: function onClose() {\n return _this2.removeAlert(i);\n }\n }, _this2.state.alerts[i])));\n };\n\n for (var i = 0; i < this.state.alerts.length; i++) {\n _loop(i);\n }\n\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](react__WEBPACK_IMPORTED_MODULE_2__[\"Fragment\"], null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"content-header\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"container-fluid\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"row mb-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"col-sm-6\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"h1\", {\n className: \"m-0 text-dark\"\n }, \"Create a new group\")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"col-sm-6\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"ol\", {\n className: \"breadcrumb float-sm-right\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"li\", {\n className: \"breadcrumb-item\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](react_router_dom__WEBPACK_IMPORTED_MODULE_1__[\"Link\"], {\n to: \"/admin/dashboard\"\n }, \"Home\")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"li\", {\n className: \"breadcrumb-item\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](react_router_dom__WEBPACK_IMPORTED_MODULE_1__[\"Link\"], {\n to: \"/admin/users\"\n }, \"Users\")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"li\", {\n className: \"breadcrumb-item active\"\n }, \"Add User\")))))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"content\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"row\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"col-lg-6 pl-5 pr-5\"\n }, alerts, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"form\", {\n role: \"form\",\n onSubmit: function onSubmit(e) {\n return _this2.submitForm(e);\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"form-group\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"label\", {\n htmlFor: \"name\"\n }, \"Group Name\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"input\", {\n type: \"text\",\n className: \"form-control\",\n placeholder: \"Name\",\n name: \"name\",\n id: \"name\",\n maxLength: 32,\n value: this.state.name,\n onChange: this.onChangeInput.bind(this)\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"form-group\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"label\", {\n htmlFor: \"color\"\n }, \"Color\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"div\", {\n className: \"input-group-prepend\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"span\", {\n className: \"input-group-text\",\n style: {\n padding: \"0.35rem 0.4rem 0 0.4rem\"\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](rc_color_picker__WEBPACK_IMPORTED_MODULE_6___default.a, {\n color: this.state.color,\n alpha: 100,\n name: \"color\",\n onChange: this.onChangeColor.bind(this),\n placement: \"topLeft\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"span\", {\n className: \"rc-color-picker-trigger\"\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"input\", {\n type: \"text\",\n className: \"form-control float-right\",\n readOnly: true,\n value: this.state.color\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](react_router_dom__WEBPACK_IMPORTED_MODULE_1__[\"Link\"], {\n to: \"/admin/users\",\n className: \"btn btn-info mt-2 mr-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](_elements_icon__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n icon: \"arrow-left\"\n }), \"\\xA0Back\"), this.state.isSubmitting ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"button\", {\n type: \"submit\",\n className: \"btn btn-primary mt-2\",\n disabled: true\n }, \"Loading\\u2026\\xA0\", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](_elements_icon__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n icon: \"circle-notch\"\n })) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](\"button\", {\n type: \"submit\",\n className: \"btn btn-primary mt-2\"\n }, \"Submit\"))))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__[\"createElement\"](react_tooltip__WEBPACK_IMPORTED_MODULE_4__[\"default\"], null));\n }\n }, {\n key: \"onChangeColor\",\n value: function onChangeColor(e) {\n this.setState(_objectSpread(_objectSpread({}, this.state), {}, {\n color: e.color\n }));\n }\n }, {\n key: \"onChangeInput\",\n value: function onChangeInput(event) {\n var target = event.target;\n var value = target.value;\n var name = target.name;\n this.setState(_objectSpread(_objectSpread({}, this.state), {}, _defineProperty({}, name, value)));\n }\n }, {\n key: \"submitForm\",\n value: function submitForm(e) {\n var _this3 = this;\n\n e.preventDefault();\n var name = this.state.name;\n var color = this.state.color;\n this.setState(_objectSpread(_objectSpread({}, this.state), {}, {\n isSubmitting: true\n }));\n this.parent.api.createGroup(name, color).then(function (res) {\n var alerts = _this3.state.alerts.slice();\n\n if (res.success) {\n alerts.push({\n message: \"Group was successfully created\",\n title: \"Success!\",\n type: \"success\"\n });\n\n _this3.setState(_objectSpread(_objectSpread({}, _this3.state), {}, {\n name: \"\",\n color: \"\",\n alerts: alerts,\n isSubmitting: false\n }));\n } else {\n alerts.push({\n message: res.msg,\n title: \"Error creating Group\",\n type: \"danger\"\n });\n\n _this3.setState(_objectSpread(_objectSpread({}, _this3.state), {}, {\n alerts: alerts,\n isSubmitting: false\n }));\n }\n });\n }\n }]);\n\n return CreateGroup;\n}(react__WEBPACK_IMPORTED_MODULE_2__[\"Component\"]);\n\n\n\n//# sourceURL=webpack:///./src/views/addgroup.js?"); /***/ }), diff --git a/src/src/views/addgroup.js b/src/src/views/addgroup.js index f673272..e66f03b 100644 --- a/src/src/views/addgroup.js +++ b/src/src/views/addgroup.js @@ -126,7 +126,7 @@ export default class CreateGroup extends React.Component { this.setState({...this.state, name: "", color: "", alerts: alerts, isSubmitting: false}); } else { alerts.push({message: res.msg, title: "Error creating Group", type: "danger"}); - this.setState({...this.state, name: "", color: "", alerts: alerts, isSubmitting: false}); + this.setState({...this.state, alerts: alerts, isSubmitting: false}); } }); }