diff --git a/app/Config/OpenAudit.php b/app/Config/OpenAudit.php
index d900fc032..f063105a6 100755
--- a/app/Config/OpenAudit.php
+++ b/app/Config/OpenAudit.php
@@ -14,7 +14,7 @@ class OpenAudit extends BaseConfig
public string $displayVersion = '5.1.0';
public int $appVersion = 20240104;
- public array $enterprise_collections = array('applications' => 'cud', 'baselines' => 'crud', 'baselines_policies' => 'crud', 'baselines_results' => 'crud', 'clouds' => 'crud', 'collectors' => 'crud', 'dashboards' => 'cud', 'discovery_scan_options' => 'cud', 'files' => 'crud', 'integrations' => 'crud', 'racks' => 'crud', 'roles' => 'cu');
+ public array $enterprise_collections = array('applications' => 'cud', 'baselines' => 'crud', 'baselines_policies' => 'crud', 'baselines_results' => 'crud', 'clouds' => 'crud', 'collectors' => 'crud', 'dashboards' => 'cud', 'discovery_scan_options' => 'cud', 'files' => 'crud', 'executables' => 'crud', 'integrations' => 'crud', 'racks' => 'crud', 'roles' => 'cu');
public array $professional_collections = array('applications' => 'r', 'clusters' => 'crud', 'dashboards' => 'r', 'discovery_scan_options' => 'r', 'maps' => 'crud', 'rules' => 'crud', 'tasks' => 'crud', 'widgets' => 'crud');
public float $microtime = 0;
public int $collector_connect_timeout = 10;
@@ -32,6 +32,7 @@ class OpenAudit extends BaseConfig
public string $server_os = '';
public string $server_platform = '';
public bool $advanced_queries = true;
+ public bool $executables = false;
public function __set($key, $value)
{
diff --git a/app/Config/Routes.php b/app/Config/Routes.php
index 0439793ee..fa2a1f888 100755
--- a/app/Config/Routes.php
+++ b/app/Config/Routes.php
@@ -15,7 +15,7 @@
*/
$collections = array('agents','applications','attributes','baselines','baselines_policies','baselines_results','clouds','clusters','collectors', 'components',
-'configuration','connections','credentials','dashboards','devices','discoveries','discovery_log','discovery_scan_options','errors','fields','files',
+'configuration','connections','credentials','dashboards','devices','discoveries','discovery_log','discovery_scan_options','errors','executables','fields','files',
'groups','integrations','ldap_servers','licenses','locations','maps','networks','nmis','orgs','queries','queue','racks','rack_devices','reports','roles',
'rules','scripts','summaries','support','tasks','users','widgets');
diff --git a/app/Helpers/components_helper.php b/app/Helpers/components_helper.php
index a3ae20540..4cf0ae68f 100644
--- a/app/Helpers/components_helper.php
+++ b/app/Helpers/components_helper.php
@@ -19,6 +19,9 @@ function match_columns($table)
if ($table === 'dns') {
$match_columns = array('ip', 'name', 'fqdn');
}
+ if ($table === 'executable') {
+ $match_columns = array('full_name', 'hash', 'inode', 'last_changed');
+ }
if ($table === 'file') {
$match_columns = array('full_name', 'hash', 'inode', 'last_changed');
}
diff --git a/app/Helpers/response_helper.php b/app/Helpers/response_helper.php
index e67c76ab7..02b23894a 100644
--- a/app/Helpers/response_helper.php
+++ b/app/Helpers/response_helper.php
@@ -1498,7 +1498,7 @@ function response_valid_actions()
*/
function response_valid_collections()
{
- return array('agents','applications','attributes','baselines','baselines_policies','baselines_results','chart','clouds','clusters','collectors','components','configuration','connections','credentials','dashboards','database','devices','discoveries','discovery_log','discovery_scan_options','errors','fields','files','groups','help','integrations','integrations_log','integrations_rules','ldap_servers','licenses','locations','logs','maps','networks','nmis','orgs','queries','queue','racks','rack_devices','reports','roles','rules','scripts','search','sessions','summaries','support','tasks','users','widgets');
+ return array('agents','applications','attributes','baselines','baselines_policies','baselines_results','chart','clouds','clusters','collectors','components','configuration','connections','credentials','dashboards','database','devices','discoveries','discovery_log','discovery_scan_options','errors','executables','fields','files','groups','help','integrations','integrations_log','integrations_rules','ldap_servers','licenses','locations','logs','maps','networks','nmis','orgs','queries','queue','racks','rack_devices','reports','roles','rules','scripts','search','sessions','summaries','support','tasks','users','widgets');
}
}
@@ -1532,7 +1532,7 @@ function response_valid_formats()
*/
function response_valid_includes()
{
- return array('application', 'attachment', 'audit_log', 'bios', 'certificate', 'change_log', 'cluster', 'credential', 'discovery_log', 'disk', 'dns', 'edit_log', 'field', 'file', 'image', 'ip', 'location', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'purchase', 'rack_devices', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows');
+ return array('application', 'attachment', 'audit_log', 'bios', 'certificate', 'change_log', 'cluster', 'credential', 'discovery_log', 'disk', 'dns', 'edit_log', 'executable', 'field', 'file', 'image', 'ip', 'location', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'purchase', 'rack_devices', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows');
}
}
@@ -1588,7 +1588,7 @@ function response_valid_permissions($collection)
*/
function response_valid_sub_resources()
{
- return array('application', 'attachment', 'audit_log', 'bios', 'certificate', 'change_log', 'cluster', 'credential', 'discovery', 'discovery_log', 'disk', 'dns', 'edit_log', 'field', 'image', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'partition_graph', 'policy', 'print_queue', 'processor', 'radio', 'route', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows', 'report', 'query', 'group');
+ return array('application', 'attachment', 'audit_log', 'bios', 'certificate', 'change_log', 'cluster', 'credential', 'discovery', 'discovery_log', 'disk', 'dns', 'edit_log', 'executable', 'field', 'image', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'partition_graph', 'policy', 'print_queue', 'processor', 'radio', 'route', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows', 'report', 'query', 'group');
}
}
diff --git a/app/Helpers/utility_helper.php b/app/Helpers/utility_helper.php
index 436fbcd23..fc38493d4 100644
--- a/app/Helpers/utility_helper.php
+++ b/app/Helpers/utility_helper.php
@@ -643,6 +643,17 @@ function collections_list()
$collections->discovery_scan_options->actions->professional = 'r';
$collections->discovery_scan_options->actions->community = 'r';
+
+ $collections->executables = new \StdClass();
+ $collections->executables->icon = 'fa fa-file-code-o';
+ $collections->executables->name = 'Executables';
+ $collections->executables->edition = 'Enterprise';
+ $collections->executables->orgs = 'b';
+ $collections->executables->actions = new \stdClass();
+ $collections->executables->actions->enterprise = 'crud';
+ $collections->executables->actions->professional = '';
+ $collections->executables->actions->community = '';
+
$collections->fields = new \StdClass();
$collections->fields->icon = 'fa fa-comments-o';
$collections->fields->name = 'Fields';
diff --git a/app/Models/ComponentsModel.php b/app/Models/ComponentsModel.php
index f53855c76..89ca746c9 100644
--- a/app/Models/ComponentsModel.php
+++ b/app/Models/ComponentsModel.php
@@ -47,7 +47,7 @@ public function collection(object $resp): array
}
if ($table === '') {
// No components.type requested, return all the below
- $tables = array('bios', 'certificate', 'disk', 'dns', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows');
+ $tables = array('bios', 'certificate', 'disk', 'dns', 'executable', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows');
}
$orgs = array();
$count = count($resp->meta->filter);
@@ -67,7 +67,7 @@ public function collection(object $resp): array
}
}
if (empty($tables)) {
- if (!in_array($table, ['audit_log', 'bios', 'certificate', 'change_log', 'discovery_log', 'disk', 'dns', 'edit_log', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows'])) {
+ if (!in_array($table, ['audit_log', 'bios', 'certificate', 'change_log', 'discovery_log', 'disk', 'dns', 'edit_log', 'executable', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows'])) {
# Invalid table
log_message('error', 'Invalid table provided to ComponentsModel::collection, ' . $table);
$_SESSION['error'] = 'Invalid table provided to ComponentsModel::collection, ' . htmlentities($table);
diff --git a/app/Models/DevicesModel.php b/app/Models/DevicesModel.php
index 61d89a752..6cfc961c3 100644
--- a/app/Models/DevicesModel.php
+++ b/app/Models/DevicesModel.php
@@ -356,7 +356,7 @@ public function includedCollection(): array
$orgs = array_unique(array_merge($instance->user->orgs, $instance->orgsModel->getUserDescendants($instance->user->orgs, $instance->orgs)));
$included = array();
- // No file, radio, san, scsi, usb
+ // No executable, file, radio, san, scsi, usb
$current = array('audit_log', 'bios', 'change_log', 'disk', 'dns', 'edit_log', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'route', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'user', 'user_group', 'variable', 'video', 'vm', 'windows');
foreach ($current as $table) {
@@ -387,7 +387,7 @@ public function includedRead(int $id = 0): array
}
$include = array();
- $current = array('bios', 'certificate', 'disk', 'dns', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows');
+ $current = array('bios', 'certificate', 'disk', 'dns', 'executable', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows');
foreach ($current as $table) {
if (empty($resp_include) or in_array($table, $resp_include)) {
$sql = "SELECT * FROM `$table` WHERE device_id = ? and current = 'y'";
diff --git a/app/Models/ExecutablesModel.php b/app/Models/ExecutablesModel.php
new file mode 100644
index 000000000..cb62b4e2e
--- /dev/null
+++ b/app/Models/ExecutablesModel.php
@@ -0,0 +1,252 @@
+db = db_connect();
+ $this->builder = $this->db->table('executables');
+ # Use the below to execute BaseModel::__construct
+ # parent::__construct();
+ }
+
+ /**
+ * Read the collection from the database
+ *
+ * @param $resp object An object containing the properties, filter, sort and limit as passed by the user
+ *
+ * @return array An array of formatted entries
+ */
+ public function collection(object $resp): array
+ {
+ $properties = $resp->meta->properties;
+ $properties[] = "orgs.name as `orgs.name`";
+ $properties[] = "orgs.id as `orgs.id`";
+ $this->builder->select($properties, false);
+ $this->builder->join('orgs', $resp->meta->collection . '.org_id = orgs.id', 'left');
+ foreach ($resp->meta->filter as $filter) {
+ if (in_array($filter->operator, ['!=', '>=', '<=', '=', '>', '<'])) {
+ $this->builder->{$filter->function}($filter->name . ' ' . $filter->operator, $filter->value);
+ } else {
+ $this->builder->{$filter->function}($filter->name, $filter->value);
+ }
+ }
+ $this->builder->orderBy($resp->meta->sort);
+ $this->builder->limit($resp->meta->limit, $resp->meta->offset);
+ $query = $this->builder->get();
+ if ($this->sqlError($this->db->error())) {
+ return array();
+ }
+ return format_data($query->getResult(), $resp->meta->collection);
+ }
+
+ /**
+ * Create an individual item in the database
+ *
+ * @param object $data The data attributes
+ *
+ * @return int|false The Integer ID of the newly created item, or false
+ */
+ public function create($data = null): ?int
+ {
+ if (empty($data)) {
+ return null;
+ }
+ $data->path = str_replace("'", '', $data->path);
+ $data->path = str_replace('"', '', $data->path);
+ $data->path = str_replace(';', '', $data->path);
+ $data->path = str_replace("\n", '', $data->path);
+ $data = $this->createFieldData('executables', $data);
+ if (empty($data)) {
+ return null;
+ }
+ $this->builder->insert($data);
+ if ($error = $this->sqlError($this->db->error())) {
+ \Config\Services::session()->setFlashdata('error', json_encode($error));
+ return null;
+ }
+ return (intval($this->db->insertID()));
+ }
+
+ /**
+ * Delete an individual item from the database, by ID
+ *
+ * @param int $id The ID of the requested item
+ *
+ * @return bool true || false depending on success
+ */
+ public function delete($id = null, bool $purge = false): bool
+ {
+ $this->builder->delete(['id' => intval($id)]);
+ if ($this->sqlError($this->db->error())) {
+ return false;
+ }
+ if ($this->db->affectedRows() !== 1) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Return an array containing arrays of related items to be stored in resp->included
+ *
+ * @param int $id The ID of the requested item
+ * @return array An array of anything needed for screen output
+ */
+ public function includedRead(int $id = 0): array
+ {
+ return array();
+ }
+
+ /**
+ * Return an array containing arrays of related items to be stored in resp->included
+ *
+ * @param int $id The ID of the requested item
+ * @return array An array of anything needed for screen output
+ */
+ public function includedCreateForm(int $id = 0): array
+ {
+ return array();
+ }
+
+
+ /**
+ * Read the entire collection from the database that the user is allowed to read
+ *
+ * @return array An array of formatted entries
+ */
+ public function listUser($where = array(), $orgs = array()): array
+ {
+ if (empty($orgs)) {
+ $instance = & get_instance();
+ $orgs = array_unique(array_merge($instance->user->orgs, $instance->orgsModel->getUserDescendants($instance->user->orgs, $instance->orgs)));
+ $orgs = array_unique(array_merge($orgs, $instance->orgsModel->getUserAscendants($instance->user->orgs, $instance->orgs)));
+ $orgs[] = 1;
+ $orgs = array_unique($orgs);
+ }
+
+ $properties = array();
+ $properties[] = 'executables.*';
+ $properties[] = 'orgs.name as `orgs.name`';
+ $this->builder->select($properties, false);
+ $this->builder->join('orgs', 'executables.org_id = orgs.id', 'left');
+ $this->builder->whereIn('orgs.id', $orgs);
+ $this->builder->where($where);
+ $query = $this->builder->get();
+ if ($this->sqlError($this->db->error())) {
+ return array();
+ }
+ return format_data($query->getResult(), 'executables');
+ }
+
+ /**
+ * Read the entire collection from the database
+ *
+ * @return array An array of all entries
+ */
+ public function listAll(): array
+ {
+ $query = $this->builder->get();
+ if ($this->sqlError($this->db->error())) {
+ return array();
+ }
+ return $query->getResult();
+ }
+
+ /**
+ * Read an individual item from the database, by ID
+ *
+ * @param int $id The ID of the requested item
+ *
+ * @return array The array containing the requested item
+ */
+ public function read(int $id = 0): array
+ {
+ $query = $this->builder->getWhere(['id' => intval($id)]);
+ if ($this->sqlError($this->db->error())) {
+ return array();
+ }
+ return format_data($query->getResult(), 'executables');
+ }
+
+ /**
+ * Reset a table
+ *
+ * @return bool Did it work or not?
+ */
+ public function reset(string $table = ''): bool
+ {
+ if ($this->tableReset('executables')) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Update an individual item in the database
+ *
+ * @param object $data The data attributes
+ *
+ * @return bool true || false depending on success
+ */
+ public function update($id = null, $data = null): bool
+ {
+ $data = $this->updateFieldData('executables', $data);
+ $this->builder->where('id', intval($id));
+ $this->builder->update($data);
+ if ($this->sqlError($this->db->error())) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * The dictionary item
+ *
+ * @return object The stdClass object containing the dictionary
+ */
+ public function dictionary(): object
+ {
+ $instance = & get_instance();
+
+ $collection = 'executables';
+ $dictionary = new stdClass();
+ $dictionary->table = $collection;
+ $dictionary->columns = new stdClass();
+
+ $dictionary->attributes = new stdClass();
+ $dictionary->attributes->collection = array('id', 'name', 'description', 'path', 'exclude', 'orgs.name');
+ $dictionary->attributes->create = array('name','org_id','path','exclude');
+ $dictionary->attributes->fields = $this->db->getFieldNames($collection);
+ $dictionary->attributes->fieldsMeta = $this->db->getFieldData($collection);
+ $dictionary->attributes->update = $this->updateFields($collection);
+
+ $dictionary->sentence = 'Open-AudIT Enterprise includes Executables, which detects executable files not know by the package manager. This feature is for Linux targets only.';
+
+ $dictionary->about = '
Open-AudIT can retrieve details about a file, ask the native package manager if they are known to it and monitor these files for changes as per other attributes in the Open-AudIT database.
Supported clients are Linux only.
' . $instance->dictionary->link . '
';
+
+ $dictionary->notes = '
Supported clients are Linux only.
';
+
+
+ $dictionary->product = 'enterprise';
+ $dictionary->columns->id = $instance->dictionary->id;
+ $dictionary->columns->name = $instance->dictionary->name;
+ $dictionary->columns->org_id = $instance->dictionary->org_id;
+ $dictionary->columns->description = $instance->dictionary->description;
+ $dictionary->columns->path = 'The path to the file or directory.';
+ $dictionary->columns->os_family = 'Unused as at 5.2.0.';
+ $dictionary->columns->exclude = 'Should this file (or pattern) be used to exclude files from being reported.';
+ $dictionary->columns->edited_by = $instance->dictionary->edited_by;
+ $dictionary->columns->edited_date = $instance->dictionary->edited_date;
+ return $dictionary;
+ }
+}
diff --git a/app/Models/ScriptsModel.php b/app/Models/ScriptsModel.php
index 86faaf2a6..549692010 100644
--- a/app/Models/ScriptsModel.php
+++ b/app/Models/ScriptsModel.php
@@ -405,6 +405,30 @@ public function download(int $id = 0): ?string
}
}
+ if (!empty($instance->config->executables) and $instance->config->executables) {
+ $sql = "SELECT * FROM executables";
+ $result = $this->db->query($sql)->getResult();
+ $exclusions = array();
+ if (!empty($result)) {
+ foreach ($result as $item) {
+ $path = str_replace('\\', '\\\\', $item->path);
+ if ($item->exclude === 'n') {
+ $replace = $find . "\nexecutables[" . ($item->id + 1) . ']="' . $path . '"';
+ $file = str_replace($find, $replace, $file);
+ }
+ if ($item->exclude === 'y') {
+ #$replace = $find . "\nexclusions[" . ($item->id + 1) . ']="' . $path . '"';
+ #$file = str_replace($find, $replace, $file);
+ $exclusions[] = $path;
+ }
+ }
+ }
+ if (!empty($exclusions)) {
+ $replace = $find . "\nexclusions=\"" . implode('|', $exclusions) . "\"";
+ $file = str_replace($find, $replace, $file);
+ }
+ }
+
// Force all line endings to be Unix style
// Windows audit scripts with Unix line endings work
// Unix audit scripts with Windows line endings do not work (bash for one, chokes)
diff --git a/app/Models/db_upgrades/db_5.2.0.php b/app/Models/db_upgrades/db_5.2.0.php
index b49754219..45638f9c8 100644
--- a/app/Models/db_upgrades/db_5.2.0.php
+++ b/app/Models/db_upgrades/db_5.2.0.php
@@ -22,6 +22,78 @@
log_message('info', (string)$db->getLastQuery());
}
+if (!$db->tableExists('executables')) {
+ $sql = "CREATE TABLE `executables` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `name` varchar(200) NOT NULL DEFAULT '',
+ `org_id` int(10) unsigned NOT NULL DEFAULT '1',
+ `path` text NOT NULL,
+ `description` text NOT NULL,
+ `os_family` varchar(50) NOT NULL DEFAULT '',
+ `exclude` enum('y', 'n') NOT NULL DEFAULT 'n',
+ `edited_by` varchar(200) NOT NULL DEFAULT '',
+ `edited_date` datetime NOT NULL DEFAULT '2000-01-01 00:00:00',
+ PRIMARY KEY (`id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;";
+ $db->query($sql);
+ $output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n";
+ log_message('info', (string)$db->getLastQuery());
+}
+
+if (!$db->tableExists('executable')) {
+ $sql = " CREATE TABLE `executable` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `device_id` int(10) unsigned DEFAULT NULL,
+ `current` enum('y','n') NOT NULL DEFAULT 'y',
+ `first_seen` datetime NOT NULL DEFAULT '2000-01-01 00:00:00',
+ `last_seen` datetime NOT NULL DEFAULT '2000-01-01 00:00:00',
+ `executable_id` int(10) unsigned DEFAULT NULL,
+ `name` varchar(200) NOT NULL DEFAULT '',
+ `full_name` text NOT NULL,
+ `description` varchar(1000) NOT NULL,
+ `package` varchar(1000) NOT NULL,
+ `size` int(10) unsigned NOT NULL DEFAULT '0',
+ `directory` text NOT NULL,
+ `hash` varchar(250) NOT NULL DEFAULT '',
+ `last_changed` varchar(100) NOT NULL DEFAULT '',
+ `meta_last_changed` varchar(100) NOT NULL DEFAULT '',
+ `permission` varchar(250) NOT NULL DEFAULT '',
+ `owner` varchar(100) NOT NULL DEFAULT '',
+ `group` varchar(100) NOT NULL DEFAULT '',
+ `type` varchar(100) NOT NULL DEFAULT '',
+ `version` varchar(100) NOT NULL DEFAULT '',
+ `inode` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `ack_by` varchar(200) NOT NULL DEFAULT '',
+ `ack_date` datetime NOT NULL DEFAULT '2000-01-01 00:00:00',
+ `notes` text NOT NULL,
+ PRIMARY KEY (`id`),
+ KEY `system_id` (`device_id`),
+ KEY `name` (`name`),
+ CONSTRAINT `executable_system_id` FOREIGN KEY (`device_id`) REFERENCES `devices` (`id`) ON DELETE CASCADE
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci";
+ $db->query($sql);
+ $output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n";
+ log_message('info', (string)$db->getLastQuery());
+}
+
+$sql = "SELECT * FROM `roles`";
+$roles = $db->query($sql)->getResult();
+$output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n";
+log_message('info', (string)$db->getLastQuery());
+
+foreach ($roles as $role) {
+ if ($role->name === 'org_admin' or $role->name === 'user') {
+ $permissions = json_decode($role->permissions);
+ if ($role->name === 'org_admin') {
+ $permissions->executables = 'crud';
+ }
+ if ($role->name === 'user') {
+ $permissions->executable = 'r';
+ }
+ $this->rolesModel->update(intval($role->id), $permissions);
+ }
+}
+
$sql = "DELETE FROM `configuration` WHERE `name` IN ('product', 'oae_product')";
$db->query($sql);
$output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n";
diff --git a/app/Views/devicesRead.php b/app/Views/devicesRead.php
index c5ad4e4ec..7a263cb16 100644
--- a/app/Views/devicesRead.php
+++ b/app/Views/devicesRead.php
@@ -126,7 +126,7 @@
+