Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Working toward v3 #474

Merged
merged 5 commits into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion components/plugins/class.plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,17 @@ module.exports = class Plugin extends Item {
uuid: Joi.string().default(() => {
return uuid.v4();
}),
version: Joi.number().required(),
version: Joi.string().required().messages({
"any.invalid": `{{#label}} needs to be a valid semver version`
}).custom((value, helpers) => {

if (semver.valid(value) === null) {
return helpers.error("any.invalid");
}

return semver.clean(value);

}),
//runlevel: Joi.number().min(0).max(2).default(0),
autostart: Joi.boolean().default(true),
enabled: Joi.boolean().default(true),
Expand Down Expand Up @@ -94,6 +104,9 @@ module.exports = class Plugin extends Item {
let content = fs.readFileSync(file);
json = JSON.parse(content);

// check in further version:
// json?.openhaus?.backend || json?.openhaus?.versions?.backend
// when a plugin provides frontend stuff or store data about itself in openhaus.plugin/openhaus.intents
if (!semver.satisfies(pkg.version, json?.backend)) {
this.logger.warn(`Plugin "${this.name}" is incompatible. It may work not properly or break something!`);
}
Expand Down
284 changes: 224 additions & 60 deletions postman.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"info": {
"_postman_id": "efc273f1-779c-4fce-a23e-82c17555ff65",
"_postman_id": "af00c0a1-994e-4e2c-aac9-422c102b70f1",
"name": "OpenHaus",
"description": "SmartHome/IoT application",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
Expand Down Expand Up @@ -1571,7 +1571,7 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"_id\": \"658188e93cde9987c3228806\",\n \"name\": \"Plugin Boilerplate Demo\",\n \"uuid\": \"6951dee2-8541-4a69-bd3e-629fdadf093a\",\n \"enabled\": true,\n \"version\": 1,\n \"intents\": [\n \"devices\",\n \"endpoints\",\n \"plugins\",\n \"rooms\",\n \"ssdp\",\n \"store\",\n \"users\",\n \"vault\"\n ]\n}",
"raw": "{\n \"_id\": \"658188e93cde9987c3228806\",\n \"name\": \"Plugin Boilerplate Demo\",\n \"uuid\": \"6951dee2-8541-4a69-bd3e-629fdadf093a\",\n \"enabled\": true,\n \"version\": \"1.0.0\",\n \"intents\": [\n \"devices\",\n \"endpoints\",\n \"plugins\",\n \"rooms\",\n \"ssdp\",\n \"store\",\n \"users\",\n \"vault\"\n ]\n}",
"options": {
"raw": {
"language": "json"
Expand Down Expand Up @@ -1642,7 +1642,7 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"New updated\",\n \"enabled\": true,\n \"autostart\": false,\n \"labels\": [\n \"worker_thread=false\",\n \"my_custom_label={\\\"json\\\":true, \\\"number\\\":0815420}\"\n ]\n}",
"raw": "{\n \"name\": \"New updated\",\n \"enabled\": true,\n \"autostart\": false,\n \"version\": \"9.2.5\",\n \"labels\": [\n \"worker_thread=false\",\n \"my_custom_label={\\\"json\\\":true, \\\"number\\\":0815420}\"\n ]\n}",
"options": {
"raw": {
"language": "json"
Expand Down Expand Up @@ -2895,61 +2895,7 @@
"script": {
"type": "text/javascript",
"exec": [
"let IGNORE = {",
" \"PUT\": [",
" \"/api/plugins/658188e93cde9987c3228806/files\"",
" ],",
" \"POST\": [",
" \"/api/plugins/658188e93cde9987c3228806/start\",",
" \"/api/endpoints/658189336fa19198939caa21/commands/6581fc8ac20cb522e02868ff\"",
" ]",
"};",
"",
"",
"console.log(\"Check ignore object\", pm.request.method, pm.request.url.toString());",
"",
"",
"if(Object.prototype.hasOwnProperty.call(IGNORE, pm.request.method)){",
"",
" let skip = IGNORE[pm.request.method].some((url) => {",
" return pm.request.url.toString().includes(url);",
" });",
"",
" console.log(\"Ignore\", pm.request.url.toString(), skip);",
"",
" if(skip){",
" return;",
" }",
"",
"}",
"",
"",
"pm.test(\"Status code 200 || 202\", () => {",
" pm.expect(pm.response.code).to.be.oneOf([",
" 200,",
" 202",
" ]);",
"});",
"",
"",
"pm.test(\"content-type = application/json\", () => {",
" pm.expect(pm.response.headers.get('Content-Type')).to.include('application/json');",
"});",
"",
"",
"pm.test(\"Response has no error field\", () => {",
"",
" let length = pm.response.headers.get(\"content-length\");",
"",
" // ignore empty response/no body",
" if(!length || Number(length) === 0){",
" return;",
" }",
"",
" let json = pm.response.json();",
" pm.expect(!json.error, true);",
"",
"});"
""
]
}
}
Expand Down Expand Up @@ -3366,6 +3312,153 @@
"response": []
}
]
},
{
"name": "Backup",
"item": [
{
"name": "Export Backup",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "http://{{HOST}}:{{PORT}}/api/system/backup/export",
"protocol": "http",
"host": [
"{{HOST}}"
],
"port": "{{PORT}}",
"path": [
"api",
"system",
"backup",
"export"
],
"query": [
{
"key": "encrypt",
"value": "false",
"description": "Should the .tgz (.tar.gz) file be encrypted?",
"disabled": true
},
{
"key": "includes[]",
"value": "database",
"description": "Should include database dump?",
"disabled": true
},
{
"key": "includes[]",
"value": "plugins",
"description": "Should include plugins folder?",
"disabled": true
},
{
"key": "includes[]",
"value": "env",
"description": "Should indlude .env file?",
"disabled": true
},
{
"key": "encode",
"value": "false",
"description": "Encode .env values as base64? (makes them not human readable, do this at least when you dont encrypt the backup)",
"disabled": true
}
]
}
},
"response": []
},
{
"name": "Import Backup",
"request": {
"method": "POST",
"header": [
{
"key": "X-ENCRYPTION-KEY",
"value": "1e3665f8a687da2d0869ff524c10e64ee1cb600df8228c6dfcc37fbec3359846",
"description": "Header value from export (If backup is encrpyted)",
"type": "text"
},
{
"key": "X-ENCRYPTION-IV",
"value": "186cfe92205c578a7f7199d3c973b8bd",
"description": "Header value from export (If backup is encrpyted)",
"type": "text"
}
],
"body": {
"mode": "file",
"file": {
"src": "/home/marc/projects/OpenHaus/tmp/backup-staging.tgz"
}
},
"url": {
"raw": "http://{{HOST}}:{{PORT}}/api/system/backup/import?truncate=true",
"protocol": "http",
"host": [
"{{HOST}}"
],
"port": "{{PORT}}",
"path": [
"api",
"system",
"backup",
"import"
],
"query": [
{
"key": "encrypt",
"value": "true",
"description": "Is the uploading file encrypted?",
"disabled": true
},
{
"key": "skipDuplicates",
"value": "true",
"description": "Skip same databse _id items",
"disabled": true
},
{
"key": "truncate",
"value": "true",
"description": "Truncate/clear database & plugin folder before restore"
},
{
"key": "decode",
"value": "true",
"description": "Decode base64 .env values",
"disabled": true
}
]
}
},
"response": []
}
]
}
],
"event": [
{
"listen": "prerequest",
"script": {
"type": "text/javascript",
"packages": {},
"exec": [
"postman.setNextRequest()"
]
}
},
{
"listen": "test",
"script": {
"type": "text/javascript",
"packages": {},
"exec": [
""
]
}
}
]
}
Expand All @@ -3376,7 +3469,12 @@
"script": {
"type": "text/javascript",
"exec": [
""
"console.log(\"Check if /system route\", pm.request.url.toString().includes(\"/system\"), pm.request.url.toString().includes(\"/auth\"))",
"",
"if(pm.request.url.toString().includes(\"/system\") || pm.request.url.toString().includes(\"/auth\")){",
" postman.setNextRequest(null);",
" return;",
"}"
]
}
},
Expand All @@ -3385,7 +3483,73 @@
"script": {
"type": "text/javascript",
"exec": [
""
"let IGNORE = {",
" \"PUT\": [",
" \"/api/plugins/658188e93cde9987c3228806/files\"",
" ],",
" \"POST\": [",
" \"/api/plugins/658188e93cde9987c3228806/start\",",
" \"/api/endpoints/658189336fa19198939caa21/commands/6581fc8ac20cb522e02868ff\"",
" ],",
" \"GET\": [",
" \"/auth\"",
" ]",
"};",
"",
"let URLS = [",
" \"auth\",",
" \"system\"",
"]",
"",
"console.log(\"Check ignore object\", pm.request.method, pm.request.url.toString());",
"",
"",
"if(Object.prototype.hasOwnProperty.call(IGNORE, pm.request.method)){",
"",
" let skip1 = IGNORE[pm.request.method].some((url) => {",
" return pm.request.url.toString().includes(url);",
" });",
"",
" let skip2 = URLS.some((url) => {",
" return pm.request.url.toString().includes(url);",
" });",
"",
"",
" console.log(\"Ignore\", pm.request.url.toString(), skip1 || skip2);",
"",
" if(skip1 || skip2){",
" return;",
" }",
"",
"}",
"",
"",
"pm.test(\"Status code 200 || 202\", () => {",
" pm.expect(pm.response.code).to.be.oneOf([",
" 200,",
" 202",
" ]);",
"});",
"",
"",
"pm.test(\"content-type = application/json\", () => {",
" pm.expect(pm.response.headers.get('Content-Type')).to.include('application/json');",
"});",
"",
"",
"pm.test(\"Response has no error field\", () => {",
"",
" let length = pm.response.headers.get(\"content-length\");",
"",
" // ignore empty response/no body",
" if(!length || Number(length) === 0){",
" return;",
" }",
"",
" let json = pm.response.json();",
" pm.expect(!json.error, true);",
"",
"});"
]
}
}
Expand Down
8 changes: 4 additions & 4 deletions tests/components/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ try {
C_COMPONENT.add({
_id,
name: "Plugin #1",
version: 1,
version: "1.2.3",
intents: ["devices", "endpoints", "plugins", "rooms", "ssdp", "store", "users", "vault"]
}, (err, item) => {
try {
Expand Down Expand Up @@ -59,13 +59,13 @@ try {

workflow(C_COMPONENT, "update", (done) => {
C_COMPONENT.update(_id, {
version: 2
version: "2.3.8"
}, (err, item) => {
try {

assert.ok(err === null);
assert.equal(item instanceof Plugin, true);
assert.equal(item.version, 2);
assert.equal(item.version, "2.3.8");

done(err);

Expand All @@ -83,7 +83,7 @@ try {

// update call 1
C_COMPONENT.update(_id, {
version: 3
version: "87.65.4321"
}),

// update call 2
Expand Down
Loading