/*
 * POSTGRESQL DATABASE SCHEMA FOR THE M/MONIT DATABASE.
 *
 * To create the database:
 * 1) Create a mmonit postgres user: createuser -U postgres -P mmonit
 * 2) Create the mmonit database: createdb -U postgres -E utf8 -O mmonit mmonit
 * 3) Create the schema: psql -U mmonit mmonit < mmonit-schema.postgresql
 */


/* ---------------------------------------------------- M/Monit system table */


CREATE TABLE mmonit (
  schemaversion INTEGER NOT NULL,
  welcome SMALLINT,
  purgeevents INTEGER,
  purgeanalytics INTEGER,
  skew INTEGER,
  programtimeout INTEGER,
  auditdefaultpasswords INTEGER,
  auditmd5passwords INTEGER,
  checkmonitversion INTEGER,
  checkmmonitversion INTEGER
);


/* -------------------------------------------------------------- Name table */


CREATE TABLE name (
  id BIGINT PRIMARY KEY,
  name CHARACTER VARYING(255) NOT NULL,
  CONSTRAINT name_name_unique UNIQUE (name)
);
CREATE INDEX name_name_index ON name (name);


/* ------------------------------------------------------------- Host tables */


CREATE TABLE host (
  id BIGINT PRIMARY KEY,
  created_at BIGINT,
  updated_at BIGINT,
  incarnation INTEGER,
  status INTEGER NOT NULL,
  nameid BIGINT NOT NULL,
  keepname INTEGER DEFAULT 0,
  monitid CHARACTER VARYING(255) NOT NULL,
  ipaddrin CHARACTER VARYING(255) NOT NULL,
  ipaddrout CHARACTER VARYING(255),
  portin INTEGER,
  portout INTEGER DEFAULT -1,
  uname CHARACTER VARYING(255),
  password CHARACTER VARYING(255),
  sslin SMALLINT,
  sslout SMALLINT DEFAULT -1,
  description TEXT,
  poll INTEGER DEFAULT 0,
  startdelay INTEGER DEFAULT 0,
  controlfilenameid BIGINT NOT NULL,
  statusmodified BIGINT,
  servicemodified BIGINT DEFAULT 0,
  serviceskew INTEGER DEFAULT -1,
  serviceup INTEGER DEFAULT 0,
  servicedown INTEGER DEFAULT 0,
  serviceunmonitorauto INTEGER,
  serviceunmonitormanual INTEGER,
  version CHARACTER VARYING(20),
  platformname CHARACTER VARYING(255),
  platformrelease CHARACTER VARYING(255),
  platformversion CHARACTER VARYING(255),
  platformmachine CHARACTER VARYING(255),
  platformcpu INTEGER DEFAULT 0,
  platformmemory BIGINT DEFAULT 0,
  platformswap BIGINT DEFAULT 0,
  platformuptime BIGINT DEFAULT 0,
  statusheartbeat SMALLINT DEFAULT 1,
  CONSTRAINT host_monitid_unique UNIQUE (monitid),
  CONSTRAINT host_nameid_fk FOREIGN KEY(nameid) REFERENCES name(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT host_controlfilenameid_fk FOREIGN KEY(controlfilenameid) REFERENCES name(id) MATCH FULL ON DELETE CASCADE
);


CREATE TABLE hostgroup (
  id BIGINT PRIMARY KEY,
  nameid BIGINT NOT NULL,
  CONSTRAINT hostgroup_nameid_fk FOREIGN KEY(nameid) REFERENCES name(id) MATCH FULL ON DELETE CASCADE
);


CREATE TABLE groupedhost (
  groupid BIGINT NOT NULL,
  hostid BIGINT NOT NULL,
  origin INTEGER DEFAULT 0,
  PRIMARY KEY(groupid, hostid),
  CONSTRAINT groupedhost_groupid_fk FOREIGN KEY(groupid) REFERENCES hostgroup(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT groupedhost_hostid_fk FOREIGN KEY(hostid) REFERENCES host(id) MATCH FULL ON DELETE CASCADE
);


/* ---------------------------------------------------------- Service tables */


CREATE TABLE service (
  id BIGINT PRIMARY KEY,
  created_at BIGINT,
  updated_at BIGINT,
  nameid BIGINT NOT NULL,
  hostid BIGINT NOT NULL,
  type INTEGER NOT NULL,
  status INTEGER NOT NULL,
  statushint INTEGER NOT NULL,
  monitoringstate INTEGER NOT NULL,
  monitoringmode INTEGER NOT NULL,
  onreboot INTEGER NOT NULL,
  statusmodified BIGINT DEFAULT 0,
  everytype INTEGER DEFAULT 0,
  everycyclenumber INTEGER DEFAULT 0,
  everycyclecounter INTEGER DEFAULT 0,
  everycron CHARACTER VARYING(255),
  CONSTRAINT service_hostid_fk FOREIGN KEY(hostid) REFERENCES host(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT service_nameid_fk FOREIGN KEY (nameid) REFERENCES name (id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX service_hostid_index ON service(hostid);


CREATE TABLE servicegroup (
  id BIGINT PRIMARY KEY,
  nameid BIGINT NOT NULL,
  hostid BIGINT NOT NULL,
  CONSTRAINT servicegroup_hostid_fk FOREIGN KEY(hostid) REFERENCES host(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT servicegroup_nameid_fk FOREIGN KEY (nameid) REFERENCES name (id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX servicegroup_hostid_index ON servicegroup(hostid);


CREATE TABLE groupedservices (
  servicegroupid BIGINT NOT NULL,
  service_nameid BIGINT NOT NULL,
  PRIMARY KEY(servicegroupid, service_nameid),
  CONSTRAINT groupedservices_servicegroupid_fk FOREIGN KEY (servicegroupid) REFERENCES servicegroup (id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT groupedservices_service_nameid_fk FOREIGN KEY (service_nameid) REFERENCES name (id) MATCH FULL ON DELETE CASCADE
);


/* --------------------------------------------------- Access control tables */


CREATE TABLE users (
  id BIGINT PRIMARY KEY,
  uname CHARACTER VARYING(20) NOT NULL,
  password CHARACTER VARYING(128) NOT NULL,
  fullname CHARACTER VARYING(255),
  title CHARACTER VARYING(255),
  email CHARACTER VARYING(255),
  phone CHARACTER VARYING(40),
  mobile CHARACTER VARYING(40),
  imname CHARACTER VARYING(255),
  imtype CHARACTER VARYING(20),
  image CHARACTER VARYING(255),
  refresh INTEGER DEFAULT 5000,
  CONSTRAINT users_uname_unique UNIQUE (uname)
);
CREATE INDEX users_uname_index ON users(uname);


CREATE TABLE roles (
  id BIGINT PRIMARY KEY,
  role CHARACTER VARYING(100) NOT NULL,
  description CHARACTER VARYING(255),
  admin SMALLINT DEFAULT 0,
  active SMALLINT DEFAULT 0,
  builtin SMALLINT DEFAULT 0,
  CONSTRAINT roles_role_unique UNIQUE (role)
);
CREATE INDEX roles_role_index ON roles(role);


CREATE TABLE rolerow (
  id BIGINT PRIMARY KEY,
  roleid BIGINT NOT NULL,
  CONSTRAINT rolerow_roleid_fk FOREIGN KEY(roleid) REFERENCES roles(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX rolerow_roleid_index ON rolerow(roleid);


CREATE TABLE rolerowhost (
  rolerowid BIGINT,
  hostid BIGINT,
  CONSTRAINT rolerowhost_rolerowid_fk FOREIGN KEY(rolerowid) REFERENCES rolerow(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT rolerowhost_hostid_fk FOREIGN KEY(hostid) REFERENCES host(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX rolerowhost_rolerowid_index ON rolerowhost(rolerowid);
CREATE INDEX rolerowhost_hostid_index ON rolerowhost(hostid);


CREATE TABLE rolerowhostgroup (
  rolerowid BIGINT,
  hostgroupid BIGINT,
  CONSTRAINT rolerowhostgroup_rolerowid_fk FOREIGN KEY(rolerowid) REFERENCES rolerow(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT rolerowhostgroup_hostgroupid_fk FOREIGN KEY(hostgroupid) REFERENCES hostgroup(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX rolerowhostgroup_rolerowid_index ON rolerowhostgroup(rolerowid);
CREATE INDEX rolerowhostgroup_hostgroupid_index ON rolerowhostgroup(hostgroupid);


CREATE TABLE rolerowpermission (
  rolerowid BIGINT,
  permission INTEGER,
  CONSTRAINT rolerowpermission_rolerowid_fk FOREIGN KEY(rolerowid) REFERENCES rolerow(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX rolerowpermission_roleid_index ON rolerowpermission(rolerowid);


CREATE TABLE userroles (
  userid BIGINT NOT NULL,
  roleid BIGINT NOT NULL,
  PRIMARY KEY(userid, roleid),
  CONSTRAINT userroles_roleid_fk FOREIGN KEY(roleid) REFERENCES roles(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT userroles_userid_fk FOREIGN KEY(userid) REFERENCES users(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX userroles_roleid_index ON userroles(roleid);


/* ------------------------------------------------------- Statistics tables */


CREATE TABLE statistics (
  id BIGINT PRIMARY KEY,
  serviceid BIGINT NOT NULL,
  type INTEGER NOT NULL,
  datatype INTEGER NOT NULL,
  descriptor CHARACTER VARYING(255),
  CONSTRAINT statistics_serviceid_fk FOREIGN KEY(serviceid) REFERENCES service(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_serviceid_index ON statistics(serviceid);
CREATE INDEX statistics_type_index ON statistics(type);


CREATE TABLE statistics_string (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value TEXT,
  CONSTRAINT statistics_string_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) ON DELETE CASCADE
);
CREATE INDEX statistics_string_statisticsid_index ON statistics_string(statisticsid);
CREATE INDEX statistics_string_collectedsec_index ON statistics_string(collectedsec);


CREATE TABLE statistics_int (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value INTEGER,
  CONSTRAINT statistics_int_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_int_statisticsid_index ON statistics_int(statisticsid);
CREATE INDEX statistics_int_collectedsec_index ON statistics_int(collectedsec);


CREATE TABLE statistics_llong (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value BIGINT,
  CONSTRAINT statistics_llong_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_llong_statisticsid_index ON statistics_llong(statisticsid);
CREATE INDEX statistics_llong_collectedsec_index ON statistics_llong(collectedsec);


CREATE TABLE statistics_float (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value REAL,
  CONSTRAINT statistics_float_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_float_statisticsid_index ON statistics_float(statisticsid);
CREATE INDEX statistics_float_collectedsec_index ON statistics_float(collectedsec);


CREATE TABLE statistics_double (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value DOUBLE PRECISION,
  CONSTRAINT statistics_double_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_double_statisticsid_index ON statistics_double(statisticsid);
CREATE INDEX statistics_double_collectedsec_index ON statistics_double(collectedsec);


CREATE TABLE statistics_aggregate_1m (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_1m_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_1m_statisticsid_index ON statistics_aggregate_1m(statisticsid);
CREATE INDEX statistics_aggregate_1m_collectedsec_index ON statistics_aggregate_1m(collectedsec);


CREATE TABLE statistics_aggregate_2m (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_2m_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_2m_statisticsid_index ON statistics_aggregate_2m(statisticsid);
CREATE INDEX statistics_aggregate_2m_collectedsec_index ON statistics_aggregate_2m(collectedsec);


CREATE TABLE statistics_aggregate_15m (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_15m_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_15m_statisticsid_index ON statistics_aggregate_15m(statisticsid);
CREATE INDEX statistics_aggregate_15m_collectedsec_index ON statistics_aggregate_15m(collectedsec);


CREATE TABLE statistics_aggregate_30m (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_30m_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_30m_statisticsid_index ON statistics_aggregate_30m(statisticsid);
CREATE INDEX statistics_aggregate_30m_collectedsec_index ON statistics_aggregate_30m(collectedsec);


CREATE TABLE statistics_aggregate_1h (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_1h_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_1h_statisticsid_index ON statistics_aggregate_1h(statisticsid);
CREATE INDEX statistics_aggregate_1h_collectedsec_index ON statistics_aggregate_1h(collectedsec);


CREATE TABLE statistics_aggregate_2h (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_2h_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_2h_statisticsid_index ON statistics_aggregate_2h(statisticsid);
CREATE INDEX statistics_aggregate_2h_collectedsec_index ON statistics_aggregate_2h(collectedsec);


CREATE TABLE statistics_aggregate_4h (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_4h_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_4h_statisticsid_index ON statistics_aggregate_4h(statisticsid);
CREATE INDEX statistics_aggregate_4h_collectedsec_index ON statistics_aggregate_4h(collectedsec);


CREATE TABLE statistics_aggregate_12h (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_12h_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_12h_statisticsid_index ON statistics_aggregate_12h(statisticsid);
CREATE INDEX statistics_aggregate_12h_collectedsec_index ON statistics_aggregate_12h(collectedsec);


CREATE TABLE statistics_aggregate_1d (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_1d_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_1d_statisticsid_index ON statistics_aggregate_1d(statisticsid);
CREATE INDEX statistics_aggregate_1d_collectedsec_index ON statistics_aggregate_1d(collectedsec);


CREATE TABLE statistics_aggregate_3d (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_3d_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_3d_statisticsid_index ON statistics_aggregate_3d(statisticsid);
CREATE INDEX statistics_aggregate_3d_collectedsec_index ON statistics_aggregate_3d(collectedsec);


CREATE TABLE statistics_aggregate_7d (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_7d_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_7d_statisticsid_index ON statistics_aggregate_7d(statisticsid);
CREATE INDEX statistics_aggregate_7d_collectedsec_index ON statistics_aggregate_7d(collectedsec);


CREATE TABLE statistics_aggregate_14d (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_14d_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_14d_statisticsid_index ON statistics_aggregate_14d(statisticsid);
CREATE INDEX statistics_aggregate_14d_collectedsec_index ON statistics_aggregate_14d(collectedsec);


CREATE TABLE statistics_aggregate_4w (
  statisticsid BIGINT,
  collectedsec BIGINT NOT NULL,
  value_avg DOUBLE PRECISION,
  count BIGINT,
  CONSTRAINT statistics_aggregate_4w_statisticsid_fk FOREIGN KEY(statisticsid) REFERENCES statistics(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_aggregate_4w_statisticsid_index ON statistics_aggregate_4w(statisticsid);
CREATE INDEX statistics_aggregate_4w_collectedsec_index ON statistics_aggregate_4w(collectedsec);


CREATE TABLE statistics_events  (
  timeframe INTEGER NOT NULL,
  hostid  BIGINT NOT NULL,
  state INTEGER NOT NULL,
  count BIGINT NOT NULL,
  CONSTRAINT statistics_events_hostid_fk FOREIGN KEY (hostid) REFERENCES host (id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX statistics_events_state_index ON statistics_events(state);
CREATE INDEX statistics_events_hostid_index ON statistics_events(hostid);


/* ------------------------------------------------------------ Event tables */


CREATE TABLE event (
  id BIGINT PRIMARY KEY,
  hostid BIGINT NOT NULL,
  serviceid BIGINT NOT NULL,
  collectedsec BIGINT NOT NULL,
  collectedusec BIGINT NOT NULL,
  service_nameid BIGINT NOT NULL,
  servicetype INTEGER NOT NULL,
  event INTEGER NOT NULL,
  state INTEGER NOT NULL,
  action INTEGER NOT NULL,
  message TEXT NOT NULL,
  hasnotice INTEGER,
  active INTEGER,
  CONSTRAINT event_hostid_fk FOREIGN KEY (hostid) REFERENCES host (id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT event_serviceid_fk FOREIGN KEY (serviceid) REFERENCES service (id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT event_service_nameid_fk FOREIGN KEY (service_nameid) REFERENCES name (id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX event_hostid_index ON event (hostid);
CREATE INDEX event_serviceid_index ON event (serviceid);
CREATE INDEX event_collectedsec_collectedusec_index ON event(collectedsec, collectedusec);
CREATE INDEX event_service_nameid_index ON event(service_nameid);
CREATE INDEX event_servicetype_index ON event (servicetype);
CREATE INDEX event_state_index ON event (state);
CREATE INDEX event_event_index ON event (event);
CREATE INDEX event_active_index ON event (active);


CREATE TABLE eventnotice (
  eventid BIGINT NOT NULL,
  date INTEGER NOT NULL,
  uname CHARACTER VARYING(20) NOT NULL, /* Note: store uname string instead of id to keep history of notes even if user is deleted */
  notice TEXT NOT NULL,
  CONSTRAINT eventnotice_eventid_fk FOREIGN KEY (eventid) REFERENCES event (id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX eventnotice_eventid_index ON eventnotice (eventid);


CREATE TABLE eventfilter (
  eventid BIGINT NOT NULL,
  userid BIGINT NOT NULL,
  CONSTRAINT eventfilter_eventid_fk FOREIGN KEY(eventid) REFERENCES event(id) ON DELETE CASCADE,
  CONSTRAINT eventfilter_userid_fk FOREIGN KEY(userid) REFERENCES users(id) ON DELETE CASCADE
);
CREATE INDEX eventfilter_eventid_index ON eventfilter(eventid);
CREATE INDEX eventfilter_userid_index ON eventfilter(userid);


/* ------------------------------------------------------------- Rule tables */


CREATE TABLE rule (
  id BIGINT PRIMARY KEY,
  created_at BIGINT,
  updated_at BIGINT,
  description CHARACTER VARYING(255),
  active SMALLINT,
  operator SMALLINT DEFAULT 0
);
CREATE INDEX rule_active_index ON rule (active);


CREATE TABLE rulerow (
  id BIGINT PRIMARY KEY,
  ruleid BIGINT NOT NULL,
  CONSTRAINT rulerow_ruleid_fk FOREIGN KEY(ruleid) REFERENCES rule(id) MATCH FULL ON DELETE CASCADE
);


CREATE TABLE rulerowhost (
  rulerowid BIGINT,
  hostid BIGINT,
  CONSTRAINT rulerowhost_rulerowid_fk FOREIGN KEY(rulerowid) REFERENCES rulerow(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT rulerowhost_hostid_fk FOREIGN KEY(hostid) REFERENCES host(id) MATCH FULL ON DELETE CASCADE
);


CREATE TABLE rulerowhostgroup (
  rulerowid BIGINT,
  hostgroupid BIGINT,
  CONSTRAINT rulerowhostgroup_rulerowid_fk FOREIGN KEY(rulerowid) REFERENCES rulerow(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT rulerowhostgroup_hostgroupid_fk FOREIGN KEY(hostgroupid) REFERENCES hostgroup(id) MATCH FULL ON DELETE CASCADE
);


CREATE TABLE rulerowservice (
  rulerowid BIGINT,
  service_nameid BIGINT,
  CONSTRAINT rulerowservice_rulerowid_fk FOREIGN KEY(rulerowid) REFERENCES rulerow(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT rulerowservice_service_nameid_fk FOREIGN KEY(service_nameid) REFERENCES name(id) MATCH FULL ON DELETE CASCADE
);


CREATE TABLE rulerowservicegroup (
  rulerowid BIGINT,
  servicegroup_nameid BIGINT,
  CONSTRAINT rulerowservicegroup_rulerowid_fk FOREIGN KEY(rulerowid) REFERENCES rulerow(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT rulerowservicegroup_servicegroup_nameid_fk FOREIGN KEY(servicegroup_nameid) REFERENCES name(id) MATCH FULL ON DELETE CASCADE
);


CREATE TABLE rulerowstate (
  rulerowid BIGINT,
  eventstate INTEGER,
  CONSTRAINT rulerowstate_rulerowid_fk FOREIGN KEY(rulerowid) REFERENCES rulerow(id) MATCH FULL ON DELETE CASCADE
);


CREATE TABLE rulerowevent (
  rulerowid BIGINT,
  eventid INTEGER,
  CONSTRAINT rulerowevent_rulerowid_fk FOREIGN KEY(rulerowid) REFERENCES rulerow(id) MATCH FULL ON DELETE CASCADE
);


CREATE TABLE actionrow (
  id BIGINT PRIMARY KEY,
  ruleid BIGINT NOT NULL,
  action INTEGER NOT NULL,
  repetition INTEGER DEFAULT 0,
  timeout INTEGER DEFAULT -1,
  CONSTRAINT actionrow_ruleid_fk FOREIGN KEY(ruleid) REFERENCES rule(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX actionrow_action_index ON actionrow(action);


CREATE TABLE actionrowtarget (
  actionrowid BIGINT NOT NULL,
  target TEXT NOT NULL,
  CONSTRAINT actionrowtarget_actionrowid_fk FOREIGN KEY(actionrowid) REFERENCES actionrow(id) MATCH FULL ON DELETE CASCADE
);


CREATE TABLE actionrowoption (
  actionrowid BIGINT NOT NULL,
  name CHARACTER VARYING(255) NOT NULL,
  value TEXT,
  CONSTRAINT actionrowoption_actionrowid_fk FOREIGN KEY(actionrowid) REFERENCES actionrow(id) MATCH FULL ON DELETE CASCADE
);


CREATE TABLE actionqueue (
  actionrowid BIGINT NOT NULL,
  eventid BIGINT NOT NULL,
  created_at BIGINT,
  process_at BIGINT,
  CONSTRAINT actionqueue_actionrowid_fk FOREIGN KEY(actionrowid) REFERENCES actionrow(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT actionqueue_eventid_fk FOREIGN KEY(eventid) REFERENCES event(id) MATCH FULL ON DELETE CASCADE
);
CREATE INDEX actionqueue_actionrowid_index ON actionqueue(actionrowid);
CREATE INDEX actionqueue_eventid_index ON actionqueue(eventid);
CREATE INDEX actionqueue_process_at_index ON actionqueue(process_at);


/* ----------------------------------------------------- Notification tables */


CREATE TABLE mailserver (
  id BIGINT PRIMARY KEY,
  hostname CHARACTER VARYING(255) NOT NULL,
  port INTEGER NOT NULL,
  uname CHARACTER VARYING(255),
  password CHARACTER VARYING(255),
  usessl SMALLINT,
  isdefault SMALLINT
);


CREATE TABLE jabberserver (
  id BIGINT PRIMARY KEY,
  hostname CHARACTER VARYING(255) NOT NULL,
  port INTEGER NOT NULL,
  uname CHARACTER VARYING(255),
  password CHARACTER VARYING(255),
  isdefault SMALLINT
);


CREATE TABLE messageformat (
  id BIGINT PRIMARY KEY,
  description CHARACTER VARYING(255),
  sendername CHARACTER VARYING(255),
  senderaddress CHARACTER VARYING(255),
  subjectsingle CHARACTER VARYING(255),
  subjectmulti CHARACTER VARYING(255),
  txtheader TEXT,
  txtbody TEXT,
  txtfooter TEXT,
  htmlheader TEXT,
  htmlbody TEXT,
  htmlfooter TEXT,
  contenttype SMALLINT,
  isdefault SMALLINT
);


CREATE TABLE messagequeue (
  deferredsize INTEGER,
  retry INTEGER,
  minbackoff INTEGER,
  maxbackoff INTEGER,
  flush INTEGER,
  maxmsgsize INTEGER,
  maxmsgevents INTEGER
);


CREATE TABLE alertservice (
  id BIGINT PRIMARY KEY,
  name VARCHAR(64) NOT NULL UNIQUE,
  description VARCHAR(255),
  endpoint VARCHAR(255),
  apikey TEXT,
  script TEXT NOT NULL,
  expanded TEXT NOT NULL,
  created_at BIGINT NOT NULL
);


/* ----------------------------------- Persistent Alert message queue tables */


CREATE TABLE message (
  id BIGINT PRIMARY KEY,
  type INTEGER,
  contenttype CHARACTER VARYING(255),
  sendername CHARACTER VARYING(255),
  senderaddress CHARACTER VARYING(255),
  subject CHARACTER VARYING(255),
  body TEXT,
  created BIGINT,
  retry INTEGER
);


CREATE TABLE messagerecipients (
  messageid BIGINT NOT NULL,
  recipient CHARACTER VARYING(255) NOT NULL,
  CONSTRAINT messagerecipients_message_fk FOREIGN KEY(messageid) REFERENCES message(id) MATCH FULL ON DELETE CASCADE
);


/* ----------------------------------------------- Persistent SESSION tables */


CREATE TABLE session (
  id CHARACTER VARYING(65) PRIMARY KEY,
  context CHARACTER VARYING(255) NOT NULL,
  ctime INTEGER NOT NULL,
  atime INTEGER NOT NULL,
  itime INTEGER NOT NULL,
  authtype CHARACTER VARYING(20),
  principal CHARACTER VARYING(255),
  data BYTEA
);


/* ------------------------------------------------------------ Initial Data */


/*
 * Defaults
 */
INSERT INTO mmonit (schemaversion, welcome, purgeevents, purgeanalytics, skew, programtimeout, auditdefaultpasswords, auditmd5passwords, checkmonitversion, checkmmonitversion) VALUES (24, 1, 11, 10, 3, 300, 1, 1, 0, 0);

/*
 * Access control
 */

INSERT INTO users (id, uname, password, fullname, title) VALUES (1, 'admin', '#25c25e73e69a57ccf78abd32f29ac9d8#da091173a92116fc7b86990368647f99228cd0b5d993e93248b501e059674b7e', 'Administrator', 'M/Monit Administrator');
INSERT INTO users (id, uname, password, fullname, title) VALUES (3, 'monit', '#f04af79fc22894afe51eb26d5a13006b#9b594557f02a0084bcd10cbb160406618312ce6612aeb8da86e57b2929fa1465', 'Monit', 'Collector');

/* Admin role: built-in role with full permissions and user management. It is protected and cannot be deleted */
INSERT INTO roles (id, role, description, admin, active, builtin) VALUES (4, 'admin', 'The Administrator role', 1, 1, 1);
INSERT INTO userroles (userid, roleid) VALUES (1, 4);
INSERT INTO rolerow (id, roleid) VALUES (8, 4);
INSERT INTO rolerowpermission (rolerowid, permission) VALUES (8, 1); /* Collector */
INSERT INTO rolerowpermission (rolerowid, permission) VALUES (8, 2); /* View */
INSERT INTO rolerowpermission (rolerowid, permission) VALUES (8, 4); /* Service Actions */

/* Normal user role: view and service control for all hosts */
INSERT INTO roles (id, role, description, admin, active, builtin) VALUES (5, 'GUI', 'The user role for GUI access', 0, 1, 0);
INSERT INTO userroles (userid, roleid) VALUES (3, 5);
INSERT INTO rolerow (id, roleid) VALUES (9, 5);
INSERT INTO rolerowpermission (rolerowid, permission) VALUES (9, 2); /* View */
INSERT INTO rolerowpermission (rolerowid, permission) VALUES (9, 4); /* Service Actions */

/* Collector role: Update all hosts via collector only (no view nor services control) */
INSERT INTO roles (id, role, description, admin, active, builtin) VALUES (6, 'collector', 'Role for posting status and events to M/Monit', 0, 1, 1);
INSERT INTO userroles (userid, roleid) VALUES (3, 6);
INSERT INTO rolerow (id, roleid) VALUES (10, 6);
INSERT INTO rolerowpermission (rolerowid, permission) VALUES (10, 1); /* Update host status via collector */

/*
 * Messaging
 */
INSERT INTO messageformat (id, description, sendername, senderaddress, subjectsingle, subjectmulti, txtbody, txtfooter, htmlheader, htmlbody, htmlfooter, contenttype, isdefault) VALUES (
1,
'Default',
'M/Monit',
'mmonit@$HOST',
'M/Monit report ($HOST: $EVENT $SERVICE on $DATE)',
'M/Monit report ($COUNT events)',
'Date:        $DATE
Host:        $HOST
Service:     $SERVICE
Action:      $ACTION
Description: $DESCRIPTION

',
'
Your faithful employee,
M/Monit',
'<html>
    <table style=''border-collapse:collapse;border:1px solid #eee; padding:5px;''>
        <tr>
            <th style=''border: 1px solid #eee; padding:5px;''><b>Date</b></th>
            <th style=''border: 1px solid #eee; padding:5px;''><b>Host</b></th>
            <th style=''border: 1px solid #eee; padding:5px;''><b>Service</b></th>
            <th style=''border: 1px solid #eee; padding:5px;''><b>Action</b></th>
            <th style=''border: 1px solid #eee; padding:5px;''><b>Description</b></th>
        </tr>
',
'        <tr>
            <td style=''border: 1px solid #eee; padding:5px;''>$DATE</td>
            <td style=''border: 1px solid #eee; padding:5px;''>$HOST</td>
            <td style=''border: 1px solid #eee; padding:5px;''>$SERVICE</td>
            <td style=''border: 1px solid #eee; padding:5px;''>$ACTION</td>
            <td style=''border: 1px solid #eee; padding:5px;''>$DESCRIPTION</td>
        </tr>
',
'    </table>
    <p>
        Your faithful employee,<br>
        M/Monit
    </p>
</html>',
0,
1);
INSERT INTO messageformat (id, description, sendername, senderaddress, subjectsingle, txtbody, contenttype, isdefault) VALUES(
2,
'Test',
'M/Monit',
'mmonit@$HOST',
'A test message from M/Monit',
'If you can read this, then I can send you alerts.

Your faithful employee,
M/Monit',
1,
0);
INSERT INTO messageformat (id, description, sendername, senderaddress, subjectsingle, subjectmulti, txtbody, contenttype, isdefault) VALUES (
3,
'Message limit reached',
'M/Monit',
'mmonit@$HOST',
'M/Monit report ($HOST: $EVENT $SERVICE on $DATE)',
'M/Monit report ($COUNT events)',
'Message size limit reached, please see the M/Monit events log.

Your faithful employee,
M/Monit',
1,
0);
INSERT INTO messagequeue (deferredsize, retry, minbackoff, maxbackoff, flush, maxmsgsize, maxmsgevents) VALUES (100, 10, 60, 3600, 30, 1048576, 100);

/* Slack Alert Service --------------------------------------------------- */
INSERT INTO alertservice(id, name, description, script, expanded, created_at)
VALUES(1, 'Slack Alert', 'A Service for sending Slack Alerts', $script$
# Generate the Slack message payload
generate_payload() {
  printf '{
  "channel": "%s",
  "text": "Alert from M/Monit",
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "*Alert from M/Monit*"
      }
    },
    {
      "type": "section",
      "fields": [
        {
          "type": "mrkdwn",
          "text": "*Date:*\n%s"
        },
        {
          "type": "mrkdwn",
          "text": "*Host:*\n%s"
        },
        {
          "type": "mrkdwn",
          "text": "*Service:*\n%s"
        },
        {
          "type": "mrkdwn",
          "text": "*Action:*\n%s"
        }
      ]
    },
    {
      "type": "section",
      "fields": [
        {
          "type": "mrkdwn",
          "text": "*Event:*\n%s"
        },
        {
          "type": "mrkdwn",
          "text": "*Description:*\n%s"
        }
      ]
    }
  ]
}' "$ENDPOINT" "$MONIT_DATE" "$MONIT_HOST" "$MONIT_SERVICE" "$MONIT_ACTION" "$MONIT_EVENT" "$MONIT_DESCRIPTION"
}
# Generate and send the payload
payload=$(generate_payload)
curl -s -X POST \
  -H "Authorization: Bearer $APIKEY" \
  -H "Content-type: application/json" \
  --data "$payload" \
  https://slack.com/api/chat.postMessage
$script$, 'noop', 1723456800);

/* Discord Alert Service --------------------------------------------------- */
INSERT INTO alertservice(id, name, description, script, expanded, created_at)
VALUES(2, 'Discord Alert', 'A Service for sending Discord Alerts', $script$
# Generate the Discord message payload
generate_payload() {
  printf '{
  "content": "Alert from M/Monit",
  "embeds": [{
    "title": "M/Monit Alert",
    "color": 15158332,
    "fields": [
      { "name": "Date", "value": "%s", "inline": true },
      { "name": "Host", "value": "%s", "inline": true },
      { "name": "Service", "value": "%s", "inline": true },
      { "name": "Action", "value": "%s", "inline": true },
      { "name": "Event", "value": "%s", "inline": false },
      { "name": "Description", "value": "%s", "inline": false }
    ]
  }]
}' "$MONIT_DATE" "$MONIT_HOST" "$MONIT_SERVICE" "$MONIT_ACTION" "$MONIT_EVENT" "$MONIT_DESCRIPTION"
}

# Generate and send the payload
payload=$(generate_payload)
curl -H "Content-Type: application/json" -d "$payload" "$ENDPOINT"
$script$, 'noop', 1723456800);

/* PagerDuty Alert Service --------------------------------------------------- */
INSERT INTO alertservice(id, name, description, script, expanded, created_at)
VALUES(3, 'PagerDuty Alert', 'A Service for sending PagerDuty Alerts', $script$
# The Integration Key should be set in the API Key field in the service configuration
INTEGRATION_KEY="$APIKEY"

# Generate the PagerDuty event payload
generate_payload() {
  printf '{
  "routing_key": "%s",
  "event_action": "trigger",
  "payload": {
    "summary": "M/Monit Alert: %s on %s",
    "source": "M/Monit",
    "severity": "critical",
    "custom_details": {
      "date": "%s",
      "host": "%s",
      "service": "%s",
      "action": "%s",
      "event": "%s",
      "description": "%s"
    }
  }
}' "$INTEGRATION_KEY" "$MONIT_EVENT" "$MONIT_HOST" "$MONIT_DATE" "$MONIT_HOST" "$MONIT_SERVICE" "$MONIT_ACTION" "$MONIT_EVENT" "$MONIT_DESCRIPTION"
}

# Generate and send the payload
payload=$(generate_payload)
curl -s -X POST -H "Content-Type: application/json" -d "$payload" \
  https://events.pagerduty.com/v2/enqueue
$script$, 'noop', 1723456800);
