490 lines
21 KiB
JavaScript
490 lines
21 KiB
JavaScript
// Schema initialization, migration execution, and database bootstrap helpers.
|
|
|
|
const { version: appVersion } = require('#root/package.json');
|
|
const { compareVersions, detectSchemaVersion, getPendingMigrations, recordSchemaVersion, runMigrations } = require('./migrations');
|
|
|
|
// Snapshot only: keep this file aligned with the current schema state.
|
|
async function ensureSchema(pool, options) {
|
|
const schemaLockName = 'pulse_signage_schema_lock';
|
|
const schemaConnection = await pool.getConnection();
|
|
|
|
try {
|
|
pool = schemaConnection;
|
|
|
|
const [lockRows] = await pool.query('SELECT GET_LOCK(?, 120) AS lock_acquired', [schemaLockName]);
|
|
if (!Number(lockRows && lockRows[0] && lockRows[0].lock_acquired)) {
|
|
throw new Error('Unable to acquire the schema migration lock.');
|
|
}
|
|
|
|
try {
|
|
const currentVersion = await detectSchemaVersion(pool);
|
|
const pendingMigrations = await getPendingMigrations(pool, { currentVersion: currentVersion });
|
|
const updateRequired = pendingMigrations.length > 0;
|
|
|
|
console.info('[schema] previous=' + currentVersion + ' current=' + appVersion + ' update=' + (updateRequired ? 'yes' : 'no'));
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS c_canvas_sizes (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
width INT NOT NULL,
|
|
height INT NOT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
UNIQUE KEY uq_canvas_sizes_dimensions (width, height)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS c_playlists (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
fade_between_slides TINYINT(1) NOT NULL DEFAULT 0,
|
|
skip_unavailable_rtmp TINYINT(1) NOT NULL DEFAULT 0,
|
|
canvas_id INT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
CONSTRAINT fk_playlists_canvas FOREIGN KEY (canvas_id) REFERENCES c_canvas_sizes(id) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS c_templates (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
canvas_size_id INT NULL,
|
|
background_image_path VARCHAR(512) NULL,
|
|
background_color VARCHAR(32) NULL,
|
|
background_gradient LONGTEXT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS c_template_regions (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
template_id INT NOT NULL,
|
|
region_key VARCHAR(100) NOT NULL,
|
|
region_type VARCHAR(20) NOT NULL,
|
|
label VARCHAR(255) NOT NULL,
|
|
font_family VARCHAR(100) NULL,
|
|
lock_ratio VARCHAR(20) NULL,
|
|
animation_json JSON NULL,
|
|
x INT NOT NULL DEFAULT 0,
|
|
y INT NOT NULL DEFAULT 0,
|
|
width INT NOT NULL DEFAULT 100,
|
|
height INT NOT NULL DEFAULT 100,
|
|
z_index INT NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS c_slides (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
title VARCHAR(255) NOT NULL,
|
|
template_id INT NULL,
|
|
content_json JSON NULL,
|
|
thumbnail_path VARCHAR(512) NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS c_playlist_slides (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
playlist_id INT NOT NULL,
|
|
slide_id INT NOT NULL,
|
|
position INT NOT NULL DEFAULT 0,
|
|
duration_seconds DECIMAL(10,3) NOT NULL DEFAULT 10.000,
|
|
use_video_duration TINYINT(1) NOT NULL DEFAULT 0,
|
|
disable_audio TINYINT(1) NOT NULL DEFAULT 1,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
CONSTRAINT fk_playlist_slides_playlist FOREIGN KEY (playlist_id) REFERENCES c_playlists(id) ON DELETE CASCADE,
|
|
CONSTRAINT fk_playlist_slides_slide FOREIGN KEY (slide_id) REFERENCES c_slides(id) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS c_playlist_slide_schedule_rules (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
playlist_slide_id INT NOT NULL,
|
|
position INT NOT NULL DEFAULT 0,
|
|
start_datetime DATETIME NULL,
|
|
end_datetime DATETIME NULL,
|
|
start_time TIME NULL,
|
|
end_time TIME NULL,
|
|
schedule_days_json JSON NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
CONSTRAINT fk_playlist_slide_schedule_rules_slide FOREIGN KEY (playlist_slide_id) REFERENCES c_playlist_slides(id) ON DELETE CASCADE,
|
|
INDEX idx_playlist_slide_schedule_rules_slide_position (playlist_slide_id, position)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS d_players (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
identifier VARCHAR(128) NOT NULL UNIQUE,
|
|
public_base_url VARCHAR(512) NULL,
|
|
internal_base_url VARCHAR(512) NULL,
|
|
last_seen_at TIMESTAMP NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS d_screens (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
slug VARCHAR(255) NOT NULL UNIQUE,
|
|
playlist_id INT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
CONSTRAINT fk_screens_playlist FOREIGN KEY (playlist_id) REFERENCES c_playlists(id) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS d_announcements (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
message TEXT NOT NULL,
|
|
short_label VARCHAR(255) NOT NULL DEFAULT '',
|
|
announcement_type VARCHAR(32) NOT NULL DEFAULT 'lower-third',
|
|
color_key VARCHAR(32) NOT NULL DEFAULT 'primary',
|
|
icon_key VARCHAR(64) NOT NULL DEFAULT 'megaphone-fill',
|
|
duration_seconds INT NULL,
|
|
expires_at TIMESTAMP NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
INDEX idx_announcements_expires_at (expires_at),
|
|
INDEX idx_announcements_modified_at (modified_at)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS d_announcement_screens (
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
announcement_id INT NOT NULL,
|
|
screen_id INT NOT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
UNIQUE KEY uq_announcement_screens_pair (announcement_id, screen_id),
|
|
INDEX idx_announcement_screens_screen_id (screen_id),
|
|
CONSTRAINT fk_announcement_screens_announcement FOREIGN KEY (announcement_id) REFERENCES d_announcements(id) ON DELETE CASCADE,
|
|
CONSTRAINT fk_announcement_screens_screen FOREIGN KEY (screen_id) REFERENCES d_screens(id) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS i_rss_feeds (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
feed_url VARCHAR(1024) NOT NULL,
|
|
enabled TINYINT(1) NOT NULL DEFAULT 1,
|
|
update_interval_value INT NOT NULL DEFAULT 60,
|
|
update_interval_unit VARCHAR(10) NOT NULL DEFAULT 'minutes',
|
|
item_limit INT NOT NULL DEFAULT 1,
|
|
last_pulled_at DATETIME NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS i_rss_feed_items (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
rss_feed_id INT NOT NULL,
|
|
position INT NOT NULL,
|
|
item_json MEDIUMTEXT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
CONSTRAINT fk_rss_feed_items_rss_feed FOREIGN KEY (rss_feed_id) REFERENCES i_rss_feeds(id) ON DELETE CASCADE,
|
|
UNIQUE KEY uq_rss_feed_items_feed_position (rss_feed_id, position)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS i_api_sources (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
api_url VARCHAR(1024) NOT NULL,
|
|
request_method VARCHAR(10) NOT NULL DEFAULT 'GET',
|
|
request_body_json MEDIUMTEXT NULL,
|
|
auth_method VARCHAR(32) NOT NULL DEFAULT 'none',
|
|
auth_username VARCHAR(255) NULL,
|
|
auth_password MEDIUMTEXT NULL,
|
|
auth_bearer_token MEDIUMTEXT NULL,
|
|
auth_header_name VARCHAR(255) NULL,
|
|
auth_header_value MEDIUMTEXT NULL,
|
|
token_url VARCHAR(1024) NULL,
|
|
token_request_body_json MEDIUMTEXT NULL,
|
|
token_response_path VARCHAR(255) NULL DEFAULT 'access_token',
|
|
token_header_name VARCHAR(255) NULL DEFAULT 'Authorization',
|
|
token_header_prefix VARCHAR(64) NULL DEFAULT 'Bearer',
|
|
items_path VARCHAR(255) NULL,
|
|
enabled TINYINT(1) NOT NULL DEFAULT 1,
|
|
update_interval_value INT NOT NULL DEFAULT 60,
|
|
update_interval_unit VARCHAR(10) NOT NULL DEFAULT 'minutes',
|
|
last_pulled_at TIMESTAMP NULL,
|
|
last_pull_error MEDIUMTEXT NULL,
|
|
last_response_status INT NULL,
|
|
last_response_content_type VARCHAR(255) NULL,
|
|
last_response_json MEDIUMTEXT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS i_weather_locations (
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL UNIQUE,
|
|
location_label VARCHAR(255) NOT NULL,
|
|
latitude DECIMAL(9,6) NOT NULL,
|
|
longitude DECIMAL(9,6) NOT NULL,
|
|
timezone VARCHAR(128) NOT NULL,
|
|
provider VARCHAR(32) NOT NULL DEFAULT 'open-meteo',
|
|
temperature_unit VARCHAR(16) NOT NULL DEFAULT 'celsius',
|
|
wind_unit VARCHAR(16) NOT NULL DEFAULT 'kmh',
|
|
precipitation_unit VARCHAR(16) NOT NULL DEFAULT 'mm',
|
|
enabled TINYINT(1) NOT NULL DEFAULT 1,
|
|
update_interval_value INT NOT NULL DEFAULT 30,
|
|
update_interval_unit VARCHAR(16) NOT NULL DEFAULT 'minutes',
|
|
last_pulled_at DATETIME NULL,
|
|
last_pull_error VARCHAR(1024) NULL,
|
|
last_response_json MEDIUMTEXT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
INDEX idx_weather_locations_modified_at (modified_at)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS i_timetable_groups (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
short_description VARCHAR(255) NULL,
|
|
timezone VARCHAR(64) NOT NULL DEFAULT 'Europe/London',
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS i_timetable_entries (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
schedule_group_id INT NOT NULL,
|
|
title VARCHAR(255) NOT NULL,
|
|
short_description VARCHAR(255) NULL,
|
|
start_datetime DATETIME NOT NULL,
|
|
end_datetime DATETIME NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
CONSTRAINT fk_timetable_entries_group FOREIGN KEY (schedule_group_id) REFERENCES i_timetable_groups(id) ON DELETE CASCADE,
|
|
INDEX idx_timetable_entries_group_start (schedule_group_id, start_datetime)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS d_onboarding_devices (
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
device_id VARCHAR(128) NOT NULL UNIQUE,
|
|
client_name VARCHAR(255) NULL,
|
|
screen_id INT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
last_seen_at TIMESTAMP NULL,
|
|
CONSTRAINT fk_player_onboarding_devices_screen FOREIGN KEY (screen_id) REFERENCES d_screens(id) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS a_users (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NULL,
|
|
username VARCHAR(255) NOT NULL UNIQUE,
|
|
password_hash CHAR(64) NOT NULL,
|
|
password_salt VARCHAR(64) NOT NULL,
|
|
password_iterations INT NOT NULL,
|
|
must_change_password TINYINT(1) NOT NULL DEFAULT 0,
|
|
account_locked TINYINT(1) NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS a_roles (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
role_key VARCHAR(100) NOT NULL UNIQUE,
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS a_permissions (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
permission_key VARCHAR(100) NOT NULL UNIQUE,
|
|
name VARCHAR(255) NOT NULL,
|
|
section_name VARCHAR(255) NOT NULL,
|
|
description TEXT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS a_role_permissions (
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
role_id INT NOT NULL,
|
|
permission_id INT NOT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
UNIQUE KEY uq_role_permissions_pair (role_id, permission_id),
|
|
CONSTRAINT fk_role_permissions_role FOREIGN KEY (role_id) REFERENCES a_roles(id) ON DELETE CASCADE,
|
|
CONSTRAINT fk_role_permissions_permission FOREIGN KEY (permission_id) REFERENCES a_permissions(id) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS a_user_roles (
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
user_id INT NOT NULL,
|
|
role_id INT NOT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
UNIQUE KEY uq_user_roles_pair (user_id, role_id),
|
|
CONSTRAINT fk_user_roles_user FOREIGN KEY (user_id) REFERENCES a_users(id) ON DELETE CASCADE,
|
|
CONSTRAINT fk_user_roles_role FOREIGN KEY (role_id) REFERENCES a_roles(id) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS a_sessions (
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
session_hash CHAR(64) NOT NULL UNIQUE,
|
|
user_id INT NOT NULL,
|
|
ip_address VARCHAR(255) NULL,
|
|
user_agent VARCHAR(512) NULL,
|
|
expires_at DATETIME NOT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
last_used_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL,
|
|
CONSTRAINT fk_auth_sessions_user FOREIGN KEY (user_id) REFERENCES a_users(id) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS a_login_attempts (
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
rate_key VARCHAR(600) NOT NULL UNIQUE,
|
|
failed_count INT NOT NULL DEFAULT 0,
|
|
last_failed_at DATETIME NULL,
|
|
locked_until DATETIME NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS o_background_tasks (
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
task_key VARCHAR(191) NULL,
|
|
task_type VARCHAR(100) NOT NULL,
|
|
title VARCHAR(255) NOT NULL,
|
|
category VARCHAR(100) NOT NULL DEFAULT 'general',
|
|
status VARCHAR(20) NOT NULL,
|
|
payload_json MEDIUMTEXT NULL,
|
|
metadata_json MEDIUMTEXT NULL,
|
|
attempts INT NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
started_at TIMESTAMP NULL,
|
|
finished_at TIMESTAMP NULL,
|
|
error_message MEDIUMTEXT NULL,
|
|
INDEX idx_background_tasks_status (status),
|
|
INDEX idx_background_tasks_key (task_key),
|
|
INDEX idx_background_tasks_type (task_type)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS o_app_settings (
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
setting_key VARCHAR(191) NOT NULL UNIQUE,
|
|
setting_value JSON NOT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by INT NULL,
|
|
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
modified_by INT NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
|
|
await runMigrations(pool, Object.assign({}, options, { currentVersion: currentVersion }));
|
|
await recordSchemaVersion(pool, appVersion);
|
|
} finally {
|
|
await pool.query('SELECT RELEASE_LOCK(?)', [schemaLockName]).catch(function () {
|
|
});
|
|
}
|
|
} finally {
|
|
schemaConnection.release();
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
ensureSchema,
|
|
};
|