BE: ensure /db - reorder scripts #1327

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
This commit is contained in:
jokob-sk
2025-12-04 09:57:46 +11:00
parent c8f3a84b92
commit ef2e7886c4
3 changed files with 76 additions and 97 deletions

View File

@@ -1,35 +0,0 @@
#!/bin/sh
# 02-ensure-folders.sh - ensure /config and /db exist under /data
set -eu
YELLOW=$(printf '\033[1;33m')
CYAN=$(printf '\033[1;36m')
RED=$(printf '\033[1;31m')
RESET=$(printf '\033[0m')
DATA_DIR=${NETALERTX_DATA:-/data}
TARGET_CONFIG=${NETALERTX_CONFIG:-${DATA_DIR}/config}
TARGET_DB=${NETALERTX_DB:-${DATA_DIR}/db}
ensure_folder() {
my_path="$1"
if [ ! -d "${my_path}" ]; then
>&2 printf "%s" "${CYAN}"
>&2 echo "Creating missing folder: ${my_path}"
>&2 printf "%s" "${RESET}"
mkdir -p "${my_path}" || {
>&2 printf "%s" "${RED}"
>&2 echo "❌ Failed to create folder: ${my_path}"
>&2 printf "%s" "${RESET}"
exit 1
}
chmod 700 "${my_path}" 2>/dev/null || true
fi
}
# Ensure subfolders exist
ensure_folder "${TARGET_CONFIG}"
ensure_folder "${TARGET_DB}"
exit 0

View File

@@ -1,32 +1,46 @@
#!/bin/sh #!/bin/sh
# This script checks if the database file exists, and if not, creates it with the initial schema. # Ensures the database exists, or creates a new one on first run.
# It is intended to be run at the first start of the application. # Intended to run only at initial startup.
# If ALWAYS_FRESH_INSTALL is true, remove the database to force a rebuild. set -eu
if [ "${ALWAYS_FRESH_INSTALL}" = "true" ]; then
if [ -f "${NETALERTX_DB_FILE}" ]; then YELLOW=$(printf '\033[1;33m')
# Provide feedback to the user. CYAN=$(printf '\033[1;36m')
>&2 echo "INFO: ALWAYS_FRESH_INSTALL is true. Removing existing database to force a fresh installation." RED=$(printf '\033[1;31m')
rm -f "${NETALERTX_DB_FILE}" "${NETALERTX_DB_FILE}-shm" "${NETALERTX_DB_FILE}-wal" RESET=$(printf '\033[0m')
fi
# Otherwise, if the db exists, exit. # Ensure DB folder exists
elif [ -f "${NETALERTX_DB_FILE}" ]; then if [ ! -d "${NETALERTX_DB}" ]; then
mkdir -p "${NETALERTX_DB}" || {
>&2 echo "ERROR: Failed to create DB directory at ${NETALERTX_DB}"
exit 1
}
chmod 700 "${NETALERTX_DB}" 2>/dev/null || true
fi
# Fresh rebuild requested
if [ "${ALWAYS_FRESH_INSTALL:-false}" = "true" ] && [ -f "${NETALERTX_DB_FILE}" ]; then
>&2 echo "INFO: ALWAYS_FRESH_INSTALL enabled — removing existing database."
rm -f "${NETALERTX_DB_FILE}" "${NETALERTX_DB_FILE}-shm" "${NETALERTX_DB_FILE}-wal"
fi
# If file exists now, nothing to do
if [ -f "${NETALERTX_DB_FILE}" ]; then
exit 0 exit 0
fi fi
CYAN=$(printf '\033[1;36m')
RESET=$(printf '\033[0m')
>&2 printf "%s" "${CYAN}" >&2 printf "%s" "${CYAN}"
>&2 cat <<EOF >&2 cat <<EOF
══════════════════════════════════════════════════════════════════════════════ ══════════════════════════════════════════════════════════════════════════════
🆕 First run detected. Building initial database schema in ${NETALERTX_DB_FILE}. 🆕 First run detected — building initial database at: ${NETALERTX_DB_FILE}
Do not interrupt this step. Once complete, consider backing up the fresh Do not interrupt this step. When complete, consider backing up the fresh
database before onboarding sensitive networks. DB before onboarding sensitive or critical networks.
══════════════════════════════════════════════════════════════════════════════ ══════════════════════════════════════════════════════════════════════════════
EOF EOF
>&2 printf "%s" "${RESET}" >&2 printf "%s" "${RESET}"
# Write all text to db file until we see "end-of-database-schema" # Write all text to db file until we see "end-of-database-schema"
sqlite3 "${NETALERTX_DB_FILE}" <<'end-of-database-schema' sqlite3 "${NETALERTX_DB_FILE}" <<'end-of-database-schema'
CREATE TABLE Events (eve_MAC STRING (50) NOT NULL COLLATE NOCASE, eve_IP STRING (50) NOT NULL COLLATE NOCASE, eve_DateTime DATETIME NOT NULL, eve_EventType STRING (30) NOT NULL COLLATE NOCASE, eve_AdditionalInfo STRING (250) DEFAULT (''), eve_PendingAlertEmail BOOLEAN NOT NULL CHECK (eve_PendingAlertEmail IN (0, 1)) DEFAULT (1), eve_PairEventRowid INTEGER); CREATE TABLE Events (eve_MAC STRING (50) NOT NULL COLLATE NOCASE, eve_IP STRING (50) NOT NULL COLLATE NOCASE, eve_DateTime DATETIME NOT NULL, eve_EventType STRING (30) NOT NULL COLLATE NOCASE, eve_AdditionalInfo STRING (250) DEFAULT (''), eve_PendingAlertEmail BOOLEAN NOT NULL CHECK (eve_PendingAlertEmail IN (0, 1)) DEFAULT (1), eve_PairEventRowid INTEGER);
@@ -91,7 +105,7 @@ CREATE TABLE IF NOT EXISTS "Parameters" (
); );
CREATE TABLE Plugins_Objects( CREATE TABLE Plugins_Objects(
"Index" INTEGER, "Index" INTEGER,
Plugin TEXT NOT NULL, Plugin TEXT NOT NULL,
Object_PrimaryID TEXT NOT NULL, Object_PrimaryID TEXT NOT NULL,
Object_SecondaryID TEXT NOT NULL, Object_SecondaryID TEXT NOT NULL,
DateTimeCreated TEXT NOT NULL, DateTimeCreated TEXT NOT NULL,
@@ -164,7 +178,7 @@ CREATE TABLE Plugins_Language_Strings(
Extra TEXT NOT NULL, Extra TEXT NOT NULL,
PRIMARY KEY("Index" AUTOINCREMENT) PRIMARY KEY("Index" AUTOINCREMENT)
); );
CREATE TABLE CurrentScan ( CREATE TABLE CurrentScan (
cur_MAC STRING(50) NOT NULL COLLATE NOCASE, cur_MAC STRING(50) NOT NULL COLLATE NOCASE,
cur_IP STRING(50) NOT NULL COLLATE NOCASE, cur_IP STRING(50) NOT NULL COLLATE NOCASE,
cur_Vendor STRING(250), cur_Vendor STRING(250),
@@ -191,11 +205,11 @@ CREATE TABLE IF NOT EXISTS "AppEvents" (
"ObjectPrimaryID" TEXT, "ObjectPrimaryID" TEXT,
"ObjectSecondaryID" TEXT, "ObjectSecondaryID" TEXT,
"ObjectForeignKey" TEXT, "ObjectForeignKey" TEXT,
"ObjectIndex" TEXT, "ObjectIndex" TEXT,
"ObjectIsNew" BOOLEAN, "ObjectIsNew" BOOLEAN,
"ObjectIsArchived" BOOLEAN, "ObjectIsArchived" BOOLEAN,
"ObjectStatusColumn" TEXT, "ObjectStatusColumn" TEXT,
"ObjectStatus" TEXT, "ObjectStatus" TEXT,
"AppEventType" TEXT, "AppEventType" TEXT,
"Helper1" TEXT, "Helper1" TEXT,
"Helper2" TEXT, "Helper2" TEXT,
@@ -233,21 +247,21 @@ CREATE INDEX IDX_dev_Favorite ON Devices (devFavorite);
CREATE INDEX IDX_dev_LastIP ON Devices (devLastIP); CREATE INDEX IDX_dev_LastIP ON Devices (devLastIP);
CREATE INDEX IDX_dev_NewDevice ON Devices (devIsNew); CREATE INDEX IDX_dev_NewDevice ON Devices (devIsNew);
CREATE INDEX IDX_dev_Archived ON Devices (devIsArchived); CREATE INDEX IDX_dev_Archived ON Devices (devIsArchived);
CREATE VIEW Events_Devices AS CREATE VIEW Events_Devices AS
SELECT * SELECT *
FROM Events FROM Events
LEFT JOIN Devices ON eve_MAC = devMac LEFT JOIN Devices ON eve_MAC = devMac
/* Events_Devices(eve_MAC,eve_IP,eve_DateTime,eve_EventType,eve_AdditionalInfo,eve_PendingAlertEmail,eve_PairEventRowid,devMac,devName,devOwner,devType,devVendor,devFavorite,devGroup,devComments,devFirstConnection,devLastConnection,devLastIP,devStaticIP,devScan,devLogEvents,devAlertEvents,devAlertDown,devSkipRepeated,devLastNotification,devPresentLastScan,devIsNew,devLocation,devIsArchived,devParentMAC,devParentPort,devIcon,devGUID,devSite,devSSID,devSyncHubNode,devSourcePlugin,devCustomProps) */; /* Events_Devices(eve_MAC,eve_IP,eve_DateTime,eve_EventType,eve_AdditionalInfo,eve_PendingAlertEmail,eve_PairEventRowid,devMac,devName,devOwner,devType,devVendor,devFavorite,devGroup,devComments,devFirstConnection,devLastConnection,devLastIP,devStaticIP,devScan,devLogEvents,devAlertEvents,devAlertDown,devSkipRepeated,devLastNotification,devPresentLastScan,devIsNew,devLocation,devIsArchived,devParentMAC,devParentPort,devIcon,devGUID,devSite,devSSID,devSyncHubNode,devSourcePlugin,devCustomProps) */;
CREATE VIEW LatestEventsPerMAC AS CREATE VIEW LatestEventsPerMAC AS
WITH RankedEvents AS ( WITH RankedEvents AS (
SELECT SELECT
e.*, e.*,
ROW_NUMBER() OVER (PARTITION BY e.eve_MAC ORDER BY e.eve_DateTime DESC) AS row_num ROW_NUMBER() OVER (PARTITION BY e.eve_MAC ORDER BY e.eve_DateTime DESC) AS row_num
FROM Events AS e FROM Events AS e
) )
SELECT SELECT
e.*, e.*,
d.*, d.*,
c.* c.*
FROM RankedEvents AS e FROM RankedEvents AS e
LEFT JOIN Devices AS d ON e.eve_MAC = d.devMac LEFT JOIN Devices AS d ON e.eve_MAC = d.devMac
@@ -286,11 +300,11 @@ CREATE VIEW Convert_Events_to_Sessions AS SELECT EVE1.eve_MAC,
CREATE TRIGGER "trg_insert_devices" CREATE TRIGGER "trg_insert_devices"
AFTER INSERT ON "Devices" AFTER INSERT ON "Devices"
WHEN NOT EXISTS ( WHEN NOT EXISTS (
SELECT 1 FROM AppEvents SELECT 1 FROM AppEvents
WHERE AppEventProcessed = 0 WHERE AppEventProcessed = 0
AND ObjectType = 'Devices' AND ObjectType = 'Devices'
AND ObjectGUID = NEW.devGUID AND ObjectGUID = NEW.devGUID
AND ObjectStatus = CASE WHEN NEW.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END AND ObjectStatus = CASE WHEN NEW.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END
AND AppEventType = 'insert' AND AppEventType = 'insert'
) )
BEGIN BEGIN
@@ -311,18 +325,18 @@ CREATE TRIGGER "trg_insert_devices"
"AppEventType" "AppEventType"
) )
VALUES ( VALUES (
lower( lower(
hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' || hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' ||
substr(hex( randomblob(2)), 2) || '-' || substr(hex( randomblob(2)), 2) || '-' ||
substr('AB89', 1 + (abs(random()) % 4) , 1) || substr('AB89', 1 + (abs(random()) % 4) , 1) ||
substr(hex(randomblob(2)), 2) || '-' || substr(hex(randomblob(2)), 2) || '-' ||
hex(randomblob(6)) hex(randomblob(6))
) )
, ,
DATETIME('now'), DATETIME('now'),
FALSE, FALSE,
'Devices', 'Devices',
NEW.devGUID, -- ObjectGUID NEW.devGUID, -- ObjectGUID
NEW.devMac, -- ObjectPrimaryID NEW.devMac, -- ObjectPrimaryID
NEW.devLastIP, -- ObjectSecondaryID NEW.devLastIP, -- ObjectSecondaryID
@@ -338,11 +352,11 @@ CREATE TRIGGER "trg_insert_devices"
CREATE TRIGGER "trg_update_devices" CREATE TRIGGER "trg_update_devices"
AFTER UPDATE ON "Devices" AFTER UPDATE ON "Devices"
WHEN NOT EXISTS ( WHEN NOT EXISTS (
SELECT 1 FROM AppEvents SELECT 1 FROM AppEvents
WHERE AppEventProcessed = 0 WHERE AppEventProcessed = 0
AND ObjectType = 'Devices' AND ObjectType = 'Devices'
AND ObjectGUID = NEW.devGUID AND ObjectGUID = NEW.devGUID
AND ObjectStatus = CASE WHEN NEW.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END AND ObjectStatus = CASE WHEN NEW.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END
AND AppEventType = 'update' AND AppEventType = 'update'
) )
BEGIN BEGIN
@@ -363,18 +377,18 @@ CREATE TRIGGER "trg_update_devices"
"AppEventType" "AppEventType"
) )
VALUES ( VALUES (
lower( lower(
hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' || hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' ||
substr(hex( randomblob(2)), 2) || '-' || substr(hex( randomblob(2)), 2) || '-' ||
substr('AB89', 1 + (abs(random()) % 4) , 1) || substr('AB89', 1 + (abs(random()) % 4) , 1) ||
substr(hex(randomblob(2)), 2) || '-' || substr(hex(randomblob(2)), 2) || '-' ||
hex(randomblob(6)) hex(randomblob(6))
) )
, ,
DATETIME('now'), DATETIME('now'),
FALSE, FALSE,
'Devices', 'Devices',
NEW.devGUID, -- ObjectGUID NEW.devGUID, -- ObjectGUID
NEW.devMac, -- ObjectPrimaryID NEW.devMac, -- ObjectPrimaryID
NEW.devLastIP, -- ObjectSecondaryID NEW.devLastIP, -- ObjectSecondaryID
@@ -390,11 +404,11 @@ CREATE TRIGGER "trg_update_devices"
CREATE TRIGGER "trg_delete_devices" CREATE TRIGGER "trg_delete_devices"
AFTER DELETE ON "Devices" AFTER DELETE ON "Devices"
WHEN NOT EXISTS ( WHEN NOT EXISTS (
SELECT 1 FROM AppEvents SELECT 1 FROM AppEvents
WHERE AppEventProcessed = 0 WHERE AppEventProcessed = 0
AND ObjectType = 'Devices' AND ObjectType = 'Devices'
AND ObjectGUID = OLD.devGUID AND ObjectGUID = OLD.devGUID
AND ObjectStatus = CASE WHEN OLD.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END AND ObjectStatus = CASE WHEN OLD.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END
AND AppEventType = 'delete' AND AppEventType = 'delete'
) )
BEGIN BEGIN
@@ -415,18 +429,18 @@ CREATE TRIGGER "trg_delete_devices"
"AppEventType" "AppEventType"
) )
VALUES ( VALUES (
lower( lower(
hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' || hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' ||
substr(hex( randomblob(2)), 2) || '-' || substr(hex( randomblob(2)), 2) || '-' ||
substr('AB89', 1 + (abs(random()) % 4) , 1) || substr('AB89', 1 + (abs(random()) % 4) , 1) ||
substr(hex(randomblob(2)), 2) || '-' || substr(hex(randomblob(2)), 2) || '-' ||
hex(randomblob(6)) hex(randomblob(6))
) )
, ,
DATETIME('now'), DATETIME('now'),
FALSE, FALSE,
'Devices', 'Devices',
OLD.devGUID, -- ObjectGUID OLD.devGUID, -- ObjectGUID
OLD.devMac, -- ObjectPrimaryID OLD.devMac, -- ObjectPrimaryID
OLD.devLastIP, -- ObjectSecondaryID OLD.devLastIP, -- ObjectSecondaryID