Bladeren bron

Server: DELETE /services/{serverId}/{serviceID}; CASCADE DELETE on all FKs; Docs: Postman Collection

Christian Kahlau 3 jaren geleden
bovenliggende
commit
d2ed07688e

+ 25 - 1
server/docs/Monitoring.postman_collection.json

@@ -127,7 +127,7 @@
 						"header": [],
 						"body": {
 							"mode": "raw",
-							"raw": "{\r\n    \"id\": 2,\r\n    \"title\": \"kaytobee.de\",\r\n    \"type\": \"http\",\r\n    \"url\": \"https://www.kaytobee.de\",\r\n    \"interval\": 50,\r\n    \"checks\": [\r\n        \"kaytobee\",\r\n        \"kaytobee\\\\.(com|de|fr)\",\r\n        \"reg|exp\"\r\n    ]\r\n}",
+							"raw": "{\r\n    \"title\": \"kaytobee.de\",\r\n    \"type\": \"http\",\r\n    \"url\": \"https://www.kaytobee.de\",\r\n    \"interval\": 50,\r\n    \"checks\": [\r\n        \"kaytobee\",\r\n        \"kaytobee\\\\.(com|de|fr)\",\r\n        \"reg|exp\"\r\n    ]\r\n}",
 							"options": {
 								"raw": {
 									"language": "json"
@@ -151,6 +151,30 @@
 						}
 					},
 					"response": []
+				},
+				{
+					"name": "/services/{:serverId} - Delete a Service Check",
+					"request": {
+						"method": "DELETE",
+						"header": [],
+						"url": {
+							"raw": "http://10.8.0.1:8880/services/3/9",
+							"protocol": "http",
+							"host": [
+								"10",
+								"8",
+								"0",
+								"1"
+							],
+							"port": "8880",
+							"path": [
+								"services",
+								"3",
+								"9"
+							]
+						}
+					},
+					"response": []
 				}
 			]
 		}

+ 11 - 0
server/src/ctrl/database.class.ts

@@ -91,6 +91,9 @@ export class Database extends SQLiteController {
         const mig = new DBMigration(this.db);
         await mig.update();
       }
+
+      // DB RUNTIME SETTINGS
+      await this.exec('PRAGMA foreign_keys=on;');
     } catch (err) {
       Logger.error('[FATAL] Initializing Database failed:', err);
       Logger.error('[EXITING]');
@@ -358,6 +361,14 @@ export class Database extends SQLiteController {
     }
   }
 
+  async deleteHealthCheckConfig(serverID: number, confID: number) {
+    const conf = await this.getHealthCheckConfigByID(serverID, confID);
+    if (!conf) return false;
+
+    await this.run('DELETE FROM HealthCheckConfig WHERE ID = ?;', [confID]);
+    return true;
+  }
+
   private configFromResultRows(rows: any[]) {
     return rows.reduce((res: ServiceConfig[], line, i) => {
       const configID = line['ID'];

+ 92 - 0
server/src/migrations/202211190031_cascade_delete.sql

@@ -0,0 +1,92 @@
+ALTER TABLE HealthCheckConfig RENAME TO HealthCheckConfig_OLD;
+
+CREATE TABLE HealthCheckConfig(
+  ID INTEGER PRIMARY KEY AUTOINCREMENT,
+  ServerID INTEGER NOT NULL,
+  Type TEXT NOT NULL,
+  Title TEXT NOT NULL,
+  CONSTRAINT FK_HealthCheckConfig_Server
+    FOREIGN KEY(ServerID)
+    REFERENCES Server(ID)
+    ON DELETE CASCADE,
+  UNIQUE(ServerID, Type, Title)
+);
+
+INSERT INTO HealthCheckConfig SELECT * FROM HealthCheckConfig_OLD;
+DROP TABLE HealthCheckConfig_OLD;
+
+ALTER TABLE HealthCheckParams RENAME TO HealthCheckParams_OLD;
+CREATE TABLE HealthCheckParams(
+  ID INTEGER PRIMARY KEY AUTOINCREMENT,
+  ConfigID INTEGER NOT NULL,
+  Type TEXT NOT NULL,
+  Key TEXT NOT NULL,
+  Value TEXT NOT NULL,
+  CONSTRAINT FK_HealthCheckParams_HealthCheckConfig 
+    FOREIGN KEY(ConfigID) 
+    REFERENCES HealthCheckConfig(ID)
+    ON DELETE CASCADE
+);
+INSERT INTO HealthCheckParams SELECT * FROM HealthCheckParams_OLD;
+DROP TABLE HealthCheckParams_OLD;
+
+ALTER TABLE HealthCheckDataEntry RENAME TO HealthCheckDataEntry_OLD;
+CREATE TABLE HealthCheckDataEntry(
+  ID INTEGER PRIMARY KEY AUTOINCREMENT,
+  ConfigID INTEGER NOT NULL,
+  Timestamp INTEGER NOT NULL,
+  Status INTEGER NOT NULL,
+  Message TEXT,
+  CONSTRAINT FK_HealthCheckDataEntry_HealthCheckConfig
+    FOREIGN KEY(ConfigID) 
+    REFERENCES HealthCheckConfig(ID)
+    ON DELETE CASCADE,
+  UNIQUE(ConfigID, Timestamp)
+);
+INSERT INTO HealthCheckDataEntry SELECT * FROM HealthCheckDataEntry_OLD;
+DROP TABLE HealthCheckDataEntry_OLD;
+
+ALTER TABLE ServerConfig RENAME TO ServerConfig_OLD;
+CREATE TABLE ServerConfig (
+  ID INTEGER PRIMARY KEY AUTOINCREMENT,
+  ServerID INTEGER NOT NULL,
+  Key TEXT NOT NULL,
+  Value TEXT NOT NULL,
+  CONSTRAINT FK_ServerConfig_Server
+    FOREIGN KEY(ServerID) 
+    REFERENCES Server(ID)
+    ON DELETE CASCADE,
+  UNIQUE(ServerID, Key)
+);
+INSERT INTO ServerConfig SELECT * FROM ServerConfig_OLD;
+DROP TABLE ServerConfig_OLD;
+
+ALTER TABLE ServerDataEntry RENAME TO ServerDataEntry_OLD;
+CREATE TABLE ServerDataEntry (
+  ID INTEGER PRIMARY KEY AUTOINCREMENT,
+  ServerID INTEGER NOT NULL,
+  Timestamp INTEGER NOT NULL,
+  CONSTRAINT FK_ServerDataEntry_Server
+    FOREIGN KEY(ServerID)
+    REFERENCES Server(ID)
+    ON DELETE CASCADE,
+  UNIQUE(ServerID, Timestamp)
+);
+INSERT INTO ServerDataEntry SELECT * FROM ServerDataEntry_OLD;
+DROP TABLE ServerDataEntry_OLD;
+
+ALTER TABLE ServerDataValue RENAME TO ServerDataValue_OLD;
+CREATE TABLE ServerDataValue (
+  ID INTEGER PRIMARY KEY AUTOINCREMENT,
+  EntryID INTEGER NOT NULL,
+  Type Text NOT NULL,
+  Key TEXT NOT NULL,
+  Value REAL NOT NULL,
+  CONSTRAINT FK_ServerDataValue_ServerDataEntry
+    FOREIGN KEY(EntryID)
+    REFERENCES ServerDataEntry(ID)
+    ON DELETE CASCADE,
+  UNIQUE(EntryID, Type, Key)
+);
+INSERT INTO ServerDataValue SELECT * FROM ServerDataValue_OLD;
+DROP TABLE ServerDataValue_OLD;

+ 20 - 7
server/src/webhdl/services-api-handler.class.ts

@@ -14,7 +14,7 @@ export class ServicesAPIHandler extends WebHandler {
 
     this.router.get('/:serverID', async (req, res, next) => {
       try {
-        const serverID = this.validateServerID(req.params.serverID);
+        const serverID = this.validateNumber(req.params.serverID, 'server id');
         const services = await this.ctrlPool.db.getHttpCheckConfigs(serverID);
 
         res.send(services);
@@ -25,7 +25,7 @@ export class ServicesAPIHandler extends WebHandler {
 
     this.router.put('/:serverID', async (req, res, next) => {
       try {
-        const serverID = this.validateServerID(req.params.serverID);
+        const serverID = this.validateNumber(req.params.serverID, 'server id');
 
         const service = await this.ctrlPool.db.saveHttpCheckConfig(serverID, req.body);
 
@@ -34,15 +34,28 @@ export class ServicesAPIHandler extends WebHandler {
         next(err);
       }
     });
+
+    this.router.delete('/:serverID/:serviceID', async (req, res, next) => {
+      try {
+        const serverID = this.validateNumber(req.params.serverID, 'server id');
+        const serviceID = this.validateNumber(req.params.serviceID, 'service id');
+
+        const deleted = await this.ctrlPool.db.deleteHealthCheckConfig(serverID, serviceID);
+
+        res.send({ deleted });
+      } catch (err) {
+        next(err);
+      }
+    });
   }
 
-  private validateServerID(id: string) {
-    const serverID = Number(id);
+  private validateNumber(id: string, field: string) {
+    const num = Number(id);
 
-    if (Number.isNaN(serverID)) {
-      throw new HttpStatusException(`Not a valid server id: ${id}`, 400);
+    if (Number.isNaN(num)) {
+      throw new HttpStatusException(`Not a valid ${field}: ${id}`, 400);
     }
 
-    return serverID;
+    return num;
   }
 }