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});
}
});
}