mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	etapi improvements and more tests
This commit is contained in:
		| @@ -53,7 +53,7 @@ CREATE TABLE IF NOT EXISTS "note_revisions" (`noteRevisionId`	TEXT NOT NULL PRIM | |||||||
|                                              `noteId`	TEXT NOT NULL, |                                              `noteId`	TEXT NOT NULL, | ||||||
|                                              type TEXT DEFAULT '' NOT NULL, |                                              type TEXT DEFAULT '' NOT NULL, | ||||||
|                                              mime TEXT DEFAULT '' NOT NULL, |                                              mime TEXT DEFAULT '' NOT NULL, | ||||||
|                                              `title`	TEXT, |                                              `title`	TEXT NOT NULL, | ||||||
|                                              `isProtected`	INT NOT NULL DEFAULT 0, |                                              `isProtected`	INT NOT NULL DEFAULT 0, | ||||||
|                                              `utcDateLastEdited` TEXT NOT NULL, |                                              `utcDateLastEdited` TEXT NOT NULL, | ||||||
|                                              `utcDateCreated` TEXT NOT NULL, |                                              `utcDateCreated` TEXT NOT NULL, | ||||||
| @@ -66,7 +66,7 @@ CREATE TABLE IF NOT EXISTS "note_revision_contents" (`noteRevisionId`	TEXT NOT N | |||||||
| CREATE TABLE IF NOT EXISTS "options" | CREATE TABLE IF NOT EXISTS "options" | ||||||
| ( | ( | ||||||
|     name TEXT not null PRIMARY KEY, |     name TEXT not null PRIMARY KEY, | ||||||
|     value TEXT, |     value TEXT not null, | ||||||
|     isSynced INTEGER default 0 not null, |     isSynced INTEGER default 0 not null, | ||||||
|     utcDateModified TEXT NOT NULL |     utcDateModified TEXT NOT NULL | ||||||
| ); | ); | ||||||
|   | |||||||
							
								
								
									
										301
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										301
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "trilium", |   "name": "trilium", | ||||||
|   "version": "0.49.3", |   "version": "0.49.4", | ||||||
|   "lockfileVersion": 1, |   "lockfileVersion": 1, | ||||||
|   "requires": true, |   "requires": true, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
| @@ -546,9 +546,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "@npmcli/fs": { |     "@npmcli/fs": { | ||||||
|       "version": "1.0.0", |       "version": "1.1.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.0.0.tgz", |       "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.0.tgz", | ||||||
|       "integrity": "sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ==", |       "integrity": "sha512-VhP1qZLXcrXRIaPoqb4YA55JQxLNF3jNR4T55IdOJa3+IFJKNYHtPvtXx8slmeMavj37vCzCfrqQM1vWLsYKLA==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "@gar/promisify": "^1.0.1", |         "@gar/promisify": "^1.0.1", | ||||||
| @@ -989,9 +989,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "agentkeepalive": { |     "agentkeepalive": { | ||||||
|       "version": "4.1.4", |       "version": "4.2.0", | ||||||
|       "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz", |       "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.0.tgz", | ||||||
|       "integrity": "sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==", |       "integrity": "sha512-0PhAp58jZNw13UJv7NVdTGb0ZcghHUb3DrZ046JiiJY/BOaTTpbwdHq2VObPCBV8M2GPh7sgrJ3AQ8Ey468LJw==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "debug": "^4.1.0", |         "debug": "^4.1.0", | ||||||
| @@ -1466,33 +1466,6 @@ | |||||||
|       "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", |       "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", | ||||||
|       "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" |       "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" | ||||||
|     }, |     }, | ||||||
|     "body-parser": { |  | ||||||
|       "version": "1.19.1", |  | ||||||
|       "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", |  | ||||||
|       "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", |  | ||||||
|       "requires": { |  | ||||||
|         "bytes": "3.1.1", |  | ||||||
|         "content-type": "~1.0.4", |  | ||||||
|         "debug": "2.6.9", |  | ||||||
|         "depd": "~1.1.2", |  | ||||||
|         "http-errors": "1.8.1", |  | ||||||
|         "iconv-lite": "0.4.24", |  | ||||||
|         "on-finished": "~2.3.0", |  | ||||||
|         "qs": "6.9.6", |  | ||||||
|         "raw-body": "2.4.2", |  | ||||||
|         "type-is": "~1.6.18" |  | ||||||
|       }, |  | ||||||
|       "dependencies": { |  | ||||||
|         "debug": { |  | ||||||
|           "version": "2.6.9", |  | ||||||
|           "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", |  | ||||||
|           "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", |  | ||||||
|           "requires": { |  | ||||||
|             "ms": "2.0.0" |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "boolbase": { |     "boolbase": { | ||||||
|       "version": "1.0.0", |       "version": "1.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", |       "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", | ||||||
| @@ -1829,11 +1802,6 @@ | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "bytes": { |  | ||||||
|       "version": "3.1.1", |  | ||||||
|       "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", |  | ||||||
|       "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==" |  | ||||||
|     }, |  | ||||||
|     "cacache": { |     "cacache": { | ||||||
|       "version": "15.3.0", |       "version": "15.3.0", | ||||||
|       "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", |       "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", | ||||||
| @@ -2224,18 +2192,18 @@ | |||||||
|       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", |       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", | ||||||
|       "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" |       "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" | ||||||
|     }, |     }, | ||||||
|  |     "color-support": { | ||||||
|  |       "version": "1.1.3", | ||||||
|  |       "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", | ||||||
|  |       "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", | ||||||
|  |       "dev": true | ||||||
|  |     }, | ||||||
|     "colorette": { |     "colorette": { | ||||||
|       "version": "2.0.16", |       "version": "2.0.16", | ||||||
|       "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", |       "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", | ||||||
|       "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", |       "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "colors": { |  | ||||||
|       "version": "1.4.0", |  | ||||||
|       "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", |  | ||||||
|       "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", |  | ||||||
|       "dev": true |  | ||||||
|     }, |  | ||||||
|     "combined-stream": { |     "combined-stream": { | ||||||
|       "version": "1.0.8", |       "version": "1.0.8", | ||||||
|       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", |       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", | ||||||
| @@ -2909,9 +2877,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "electron": { |     "electron": { | ||||||
|       "version": "16.0.6", |       "version": "16.0.7", | ||||||
|       "resolved": "https://registry.npmjs.org/electron/-/electron-16.0.6.tgz", |       "resolved": "https://registry.npmjs.org/electron/-/electron-16.0.7.tgz", | ||||||
|       "integrity": "sha512-Xs9dYLYhcJf3wXn8m2gDqFTb1L862KEhMxOx9swfFBHj6NoUPPtUgw/RyPQ0tXN1XPxG9vnBkoI0BdcKwrLKuQ==", |       "integrity": "sha512-/IMwpBf2svhA1X/7Q58RV+Nn0fvUJsHniG4TizaO7q4iKFYSQ6hBvsLz+cylcZ8hRMKmVy5G1XaMNJID2ah23w==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "@electron/get": "^1.13.0", |         "@electron/get": "^1.13.0", | ||||||
| @@ -2937,9 +2905,9 @@ | |||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
|         "@types/node": { |         "@types/node": { | ||||||
|           "version": "14.18.1", |           "version": "14.18.5", | ||||||
|           "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.1.tgz", |           "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.5.tgz", | ||||||
|           "integrity": "sha512-fTFWOFrgAkj737w1o0HLTIgisgYHnsZfeiqhG1Ltrf/iJjudEbUwetQAsfrtVE49JGwvpEzQR+EbMkIqG4227g==", |           "integrity": "sha512-LMy+vDDcQR48EZdEx5wRX1q/sEl6NdGuHXPnfeL8ixkwCOSZ2qnIyIZmcCbdX0MeRqHhAcHmX+haCbrS8Run+A==", | ||||||
|           "dev": true |           "dev": true | ||||||
|         }, |         }, | ||||||
|         "boolean": { |         "boolean": { | ||||||
| @@ -3554,18 +3522,18 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "electron-rebuild": { |     "electron-rebuild": { | ||||||
|       "version": "3.2.5", |       "version": "3.2.7", | ||||||
|       "resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-3.2.5.tgz", |       "resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-3.2.7.tgz", | ||||||
|       "integrity": "sha512-U9dKi10V9w/BdIVB8a8dTKYLK3Q1d2WZ+Yo5qfM3XX/O4jI7KpnwgvWgGoVv0jTWPC2NlebF00ffWS/8NfUAtA==", |       "integrity": "sha512-WvaW1EgRinDQ61khHFZfx30rkPQG5ItaOT0wrI7iJv9A3SbghriQGfZQfHZs25fWLBe6/vkv05LOqg6aDw6Wzw==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "@malept/cross-spawn-promise": "^2.0.0", |         "@malept/cross-spawn-promise": "^2.0.0", | ||||||
|         "colors": "^1.3.3", |         "chalk": "^4.0.0", | ||||||
|         "debug": "^4.1.1", |         "debug": "^4.1.1", | ||||||
|         "detect-libc": "^1.0.3", |         "detect-libc": "^1.0.3", | ||||||
|         "fs-extra": "^10.0.0", |         "fs-extra": "^10.0.0", | ||||||
|         "got": "^11.7.0", |         "got": "^11.7.0", | ||||||
|         "lzma-native": "^8.0.1", |         "lzma-native": "^8.0.5", | ||||||
|         "node-abi": "^3.0.0", |         "node-abi": "^3.0.0", | ||||||
|         "node-api-version": "^0.1.4", |         "node-api-version": "^0.1.4", | ||||||
|         "node-gyp": "^8.4.0", |         "node-gyp": "^8.4.0", | ||||||
| @@ -3585,9 +3553,9 @@ | |||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
|         "@sindresorhus/is": { |         "@sindresorhus/is": { | ||||||
|           "version": "4.2.0", |           "version": "4.2.1", | ||||||
|           "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", |           "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.1.tgz", | ||||||
|           "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==", |           "integrity": "sha512-BrzrgtaqEre0qfvI8sMTaEvx+bayuhPmfe2rfeUGPPHYr/PLxCOqkOe4TQTDPb+qcqgNcsAtXV/Ew74mcDIE8w==", | ||||||
|           "dev": true |           "dev": true | ||||||
|         }, |         }, | ||||||
|         "@szmarczak/http-timer": { |         "@szmarczak/http-timer": { | ||||||
| @@ -3599,6 +3567,15 @@ | |||||||
|             "defer-to-connect": "^2.0.0" |             "defer-to-connect": "^2.0.0" | ||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
|  |         "ansi-styles": { | ||||||
|  |           "version": "4.3.0", | ||||||
|  |           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", | ||||||
|  |           "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", | ||||||
|  |           "dev": true, | ||||||
|  |           "requires": { | ||||||
|  |             "color-convert": "^2.0.1" | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|         "cacheable-request": { |         "cacheable-request": { | ||||||
|           "version": "7.0.2", |           "version": "7.0.2", | ||||||
|           "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", |           "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", | ||||||
| @@ -3614,6 +3591,31 @@ | |||||||
|             "responselike": "^2.0.0" |             "responselike": "^2.0.0" | ||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
|  |         "chalk": { | ||||||
|  |           "version": "4.1.2", | ||||||
|  |           "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", | ||||||
|  |           "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", | ||||||
|  |           "dev": true, | ||||||
|  |           "requires": { | ||||||
|  |             "ansi-styles": "^4.1.0", | ||||||
|  |             "supports-color": "^7.1.0" | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "color-convert": { | ||||||
|  |           "version": "2.0.1", | ||||||
|  |           "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", | ||||||
|  |           "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", | ||||||
|  |           "dev": true, | ||||||
|  |           "requires": { | ||||||
|  |             "color-name": "~1.1.4" | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "color-name": { | ||||||
|  |           "version": "1.1.4", | ||||||
|  |           "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", | ||||||
|  |           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", | ||||||
|  |           "dev": true | ||||||
|  |         }, | ||||||
|         "decompress-response": { |         "decompress-response": { | ||||||
|           "version": "6.0.0", |           "version": "6.0.0", | ||||||
|           "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", |           "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", | ||||||
| @@ -3639,9 +3641,9 @@ | |||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
|         "got": { |         "got": { | ||||||
|           "version": "11.8.2", |           "version": "11.8.3", | ||||||
|           "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", |           "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", | ||||||
|           "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", |           "integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==", | ||||||
|           "dev": true, |           "dev": true, | ||||||
|           "requires": { |           "requires": { | ||||||
|             "@sindresorhus/is": "^4.0.0", |             "@sindresorhus/is": "^4.0.0", | ||||||
| @@ -3649,7 +3651,7 @@ | |||||||
|             "@types/cacheable-request": "^6.0.1", |             "@types/cacheable-request": "^6.0.1", | ||||||
|             "@types/responselike": "^1.0.0", |             "@types/responselike": "^1.0.0", | ||||||
|             "cacheable-lookup": "^5.0.3", |             "cacheable-lookup": "^5.0.3", | ||||||
|             "cacheable-request": "^7.0.1", |             "cacheable-request": "^7.0.2", | ||||||
|             "decompress-response": "^6.0.0", |             "decompress-response": "^6.0.0", | ||||||
|             "http2-wrapper": "^1.0.0-beta.5.2", |             "http2-wrapper": "^1.0.0-beta.5.2", | ||||||
|             "lowercase-keys": "^2.0.0", |             "lowercase-keys": "^2.0.0", | ||||||
| @@ -3664,9 +3666,9 @@ | |||||||
|           "dev": true |           "dev": true | ||||||
|         }, |         }, | ||||||
|         "keyv": { |         "keyv": { | ||||||
|           "version": "4.0.4", |           "version": "4.0.5", | ||||||
|           "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.4.tgz", |           "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.5.tgz", | ||||||
|           "integrity": "sha512-vqNHbAc8BBsxk+7QBYLW0Y219rWcClspR6WSeoHYKG5mnsSoOH+BL1pWq02DDCVdvvuUny5rkBlzMRzoqc+GIg==", |           "integrity": "sha512-531pkGLqV3BMg0eDqqJFI0R1mkK1Nm5xIP2mM6keP5P8WfFtCkg2IOwplTUmlGoTgIg9yQYZ/kdihhz89XH3vA==", | ||||||
|           "dev": true, |           "dev": true, | ||||||
|           "requires": { |           "requires": { | ||||||
|             "json-buffer": "3.0.1" |             "json-buffer": "3.0.1" | ||||||
| @@ -4092,9 +4094,9 @@ | |||||||
|       "integrity": "sha512-o1JrraDGpMFaPtkuvtZ4cIBC/xuJn90KBGlxRrm3FxcfER1bPaBnBsTnypF65p+CMTXul2KrZodb3Vv3MScB4A==" |       "integrity": "sha512-o1JrraDGpMFaPtkuvtZ4cIBC/xuJn90KBGlxRrm3FxcfER1bPaBnBsTnypF65p+CMTXul2KrZodb3Vv3MScB4A==" | ||||||
|     }, |     }, | ||||||
|     "express-rate-limit": { |     "express-rate-limit": { | ||||||
|       "version": "6.0.5", |       "version": "6.1.0", | ||||||
|       "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.0.5.tgz", |       "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.1.0.tgz", | ||||||
|       "integrity": "sha512-EB1mRTrzyyPfEsQZIQFXocd8NKZoDZbEwrtbdgkc20Yed6oYg02Xfjza2HHPI/0orp54BrFeHeT92ICB9ydokw==" |       "integrity": "sha512-OWyJUDYVq/hRxGU3ufTnXDer5bRBwFiq5D35ZSZ9B2EHdjulWO4bwrbg+iIrapodDZse/35obeOj7igRHuP3Zw==" | ||||||
|     }, |     }, | ||||||
|     "express-session": { |     "express-session": { | ||||||
|       "version": "1.17.2", |       "version": "1.17.2", | ||||||
| @@ -4770,35 +4772,6 @@ | |||||||
|       "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", |       "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "http-errors": { |  | ||||||
|       "version": "1.8.1", |  | ||||||
|       "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", |  | ||||||
|       "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", |  | ||||||
|       "requires": { |  | ||||||
|         "depd": "~1.1.2", |  | ||||||
|         "inherits": "2.0.4", |  | ||||||
|         "setprototypeof": "1.2.0", |  | ||||||
|         "statuses": ">= 1.5.0 < 2", |  | ||||||
|         "toidentifier": "1.0.1" |  | ||||||
|       }, |  | ||||||
|       "dependencies": { |  | ||||||
|         "inherits": { |  | ||||||
|           "version": "2.0.4", |  | ||||||
|           "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", |  | ||||||
|           "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" |  | ||||||
|         }, |  | ||||||
|         "setprototypeof": { |  | ||||||
|           "version": "1.2.0", |  | ||||||
|           "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", |  | ||||||
|           "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" |  | ||||||
|         }, |  | ||||||
|         "toidentifier": { |  | ||||||
|           "version": "1.0.1", |  | ||||||
|           "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", |  | ||||||
|           "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "http-proxy-agent": { |     "http-proxy-agent": { | ||||||
|       "version": "5.0.0", |       "version": "5.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", |       "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", | ||||||
| @@ -5183,9 +5156,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "jasmine": { |     "jasmine": { | ||||||
|       "version": "4.0.1", |       "version": "4.0.2", | ||||||
|       "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-4.0.1.tgz", |       "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-4.0.2.tgz", | ||||||
|       "integrity": "sha512-NAf9b80ie0pAXLW2l+Fxc8s0Q6SjVgi81jOyHJRQuZ+fPjbVAnXNfN2nIwf5yoRjoSTROyRiETjr9Cr+nNBTVw==", |       "integrity": "sha512-YsrgxJQEggxzByYe4j68eQLOiQeSrPDYGv4sHhGBp3c6HHdq+uPXeAQ73kOAQpdLZ3/0zN7x/TZTloqeE1/qIA==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "glob": "^7.1.6", |         "glob": "^7.1.6", | ||||||
| @@ -5678,9 +5651,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "lzma-native": { |     "lzma-native": { | ||||||
|       "version": "8.0.1", |       "version": "8.0.5", | ||||||
|       "resolved": "https://registry.npmjs.org/lzma-native/-/lzma-native-8.0.1.tgz", |       "resolved": "https://registry.npmjs.org/lzma-native/-/lzma-native-8.0.5.tgz", | ||||||
|       "integrity": "sha512-Ryr9X3yDVZhRYOxR8QhUBCNe6GdEfy9BvFDIFtUvEkocvSvnrYt9lRm6FR1z0eQn0QSMenrgrDIJRMgUf9zsKQ==", |       "integrity": "sha512-lEkBBmePuYBycdlK8ul/sKQuZW47FMxAdjeTgDZLY4duX5Q067JJLUueyzN0wCAw6t2Y6YXCcAqHA5A1jQ9ttQ==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "node-addon-api": "^3.1.0", |         "node-addon-api": "^3.1.0", | ||||||
| @@ -6050,9 +6023,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node-gyp": { |     "node-gyp": { | ||||||
|       "version": "8.4.0", |       "version": "8.4.1", | ||||||
|       "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.0.tgz", |       "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", | ||||||
|       "integrity": "sha512-Bi/oCm5bH6F+FmzfUxJpPaxMEyIhszULGR3TprmTeku8/dMFcdTcypk120NeZqEt54r1BrgEKtm2jJiuIKE28Q==", |       "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "env-paths": "^2.2.0", |         "env-paths": "^2.2.0", | ||||||
| @@ -6060,11 +6033,95 @@ | |||||||
|         "graceful-fs": "^4.2.6", |         "graceful-fs": "^4.2.6", | ||||||
|         "make-fetch-happen": "^9.1.0", |         "make-fetch-happen": "^9.1.0", | ||||||
|         "nopt": "^5.0.0", |         "nopt": "^5.0.0", | ||||||
|         "npmlog": "^4.1.2", |         "npmlog": "^6.0.0", | ||||||
|         "rimraf": "^3.0.2", |         "rimraf": "^3.0.2", | ||||||
|         "semver": "^7.3.5", |         "semver": "^7.3.5", | ||||||
|         "tar": "^6.1.2", |         "tar": "^6.1.2", | ||||||
|         "which": "^2.0.2" |         "which": "^2.0.2" | ||||||
|  |       }, | ||||||
|  |       "dependencies": { | ||||||
|  |         "ansi-regex": { | ||||||
|  |           "version": "5.0.1", | ||||||
|  |           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", | ||||||
|  |           "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", | ||||||
|  |           "dev": true | ||||||
|  |         }, | ||||||
|  |         "are-we-there-yet": { | ||||||
|  |           "version": "2.0.0", | ||||||
|  |           "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", | ||||||
|  |           "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", | ||||||
|  |           "dev": true, | ||||||
|  |           "requires": { | ||||||
|  |             "delegates": "^1.0.0", | ||||||
|  |             "readable-stream": "^3.6.0" | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "gauge": { | ||||||
|  |           "version": "4.0.0", | ||||||
|  |           "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.0.tgz", | ||||||
|  |           "integrity": "sha512-F8sU45yQpjQjxKkm1UOAhf0U/O0aFt//Fl7hsrNVto+patMHjs7dPI9mFOGUKbhrgKm0S3EjW3scMFuQmWSROw==", | ||||||
|  |           "dev": true, | ||||||
|  |           "requires": { | ||||||
|  |             "ansi-regex": "^5.0.1", | ||||||
|  |             "aproba": "^1.0.3 || ^2.0.0", | ||||||
|  |             "color-support": "^1.1.2", | ||||||
|  |             "console-control-strings": "^1.0.0", | ||||||
|  |             "has-unicode": "^2.0.1", | ||||||
|  |             "signal-exit": "^3.0.0", | ||||||
|  |             "string-width": "^4.2.3", | ||||||
|  |             "strip-ansi": "^6.0.1", | ||||||
|  |             "wide-align": "^1.1.2" | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "is-fullwidth-code-point": { | ||||||
|  |           "version": "3.0.0", | ||||||
|  |           "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", | ||||||
|  |           "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", | ||||||
|  |           "dev": true | ||||||
|  |         }, | ||||||
|  |         "npmlog": { | ||||||
|  |           "version": "6.0.0", | ||||||
|  |           "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.0.tgz", | ||||||
|  |           "integrity": "sha512-03ppFRGlsyUaQFbGC2C8QWJN/C/K7PsfyD9aQdhVKAQIH4sQBc8WASqFBP7O+Ut4d2oo5LoeoboB3cGdBZSp6Q==", | ||||||
|  |           "dev": true, | ||||||
|  |           "requires": { | ||||||
|  |             "are-we-there-yet": "^2.0.0", | ||||||
|  |             "console-control-strings": "^1.1.0", | ||||||
|  |             "gauge": "^4.0.0", | ||||||
|  |             "set-blocking": "^2.0.0" | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "readable-stream": { | ||||||
|  |           "version": "3.6.0", | ||||||
|  |           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", | ||||||
|  |           "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", | ||||||
|  |           "dev": true, | ||||||
|  |           "requires": { | ||||||
|  |             "inherits": "^2.0.3", | ||||||
|  |             "string_decoder": "^1.1.1", | ||||||
|  |             "util-deprecate": "^1.0.1" | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "string-width": { | ||||||
|  |           "version": "4.2.3", | ||||||
|  |           "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", | ||||||
|  |           "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", | ||||||
|  |           "dev": true, | ||||||
|  |           "requires": { | ||||||
|  |             "emoji-regex": "^8.0.0", | ||||||
|  |             "is-fullwidth-code-point": "^3.0.0", | ||||||
|  |             "strip-ansi": "^6.0.1" | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "strip-ansi": { | ||||||
|  |           "version": "6.0.1", | ||||||
|  |           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", | ||||||
|  |           "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", | ||||||
|  |           "dev": true, | ||||||
|  |           "requires": { | ||||||
|  |             "ansi-regex": "^5.0.1" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node-gyp-build": { |     "node-gyp-build": { | ||||||
| @@ -6739,11 +6796,6 @@ | |||||||
|         "escape-goat": "^2.0.0" |         "escape-goat": "^2.0.0" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "qs": { |  | ||||||
|       "version": "6.9.6", |  | ||||||
|       "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", |  | ||||||
|       "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" |  | ||||||
|     }, |  | ||||||
|     "quick-lru": { |     "quick-lru": { | ||||||
|       "version": "5.1.1", |       "version": "5.1.1", | ||||||
|       "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", |       "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", | ||||||
| @@ -6774,17 +6826,6 @@ | |||||||
|       "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", |       "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", | ||||||
|       "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" |       "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" | ||||||
|     }, |     }, | ||||||
|     "raw-body": { |  | ||||||
|       "version": "2.4.2", |  | ||||||
|       "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", |  | ||||||
|       "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", |  | ||||||
|       "requires": { |  | ||||||
|         "bytes": "3.1.1", |  | ||||||
|         "http-errors": "1.8.1", |  | ||||||
|         "iconv-lite": "0.4.24", |  | ||||||
|         "unpipe": "1.0.0" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "rc": { |     "rc": { | ||||||
|       "version": "1.2.8", |       "version": "1.2.8", | ||||||
|       "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", |       "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", | ||||||
| @@ -7452,9 +7493,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "socks-proxy-agent": { |     "socks-proxy-agent": { | ||||||
|       "version": "6.1.0", |       "version": "6.1.1", | ||||||
|       "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.0.tgz", |       "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", | ||||||
|       "integrity": "sha512-57e7lwCN4Tzt3mXz25VxOErJKXlPfXmkMLnk310v/jwW20jWRVcgsOit+xNkN3eIEdB47GwnfAEBLacZ/wVIKg==", |       "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "requires": { |       "requires": { | ||||||
|         "agent-base": "^6.0.2", |         "agent-base": "^6.0.2", | ||||||
| @@ -7463,9 +7504,9 @@ | |||||||
|       }, |       }, | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "debug": { |         "debug": { | ||||||
|           "version": "4.3.2", |           "version": "4.3.3", | ||||||
|           "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", |           "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", | ||||||
|           "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", |           "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", | ||||||
|           "dev": true, |           "dev": true, | ||||||
|           "requires": { |           "requires": { | ||||||
|             "ms": "2.1.2" |             "ms": "2.1.2" | ||||||
|   | |||||||
| @@ -28,7 +28,6 @@ | |||||||
|     "async-mutex": "0.3.2", |     "async-mutex": "0.3.2", | ||||||
|     "axios": "0.24.0", |     "axios": "0.24.0", | ||||||
|     "better-sqlite3": "7.4.5", |     "better-sqlite3": "7.4.5", | ||||||
|     "body-parser": "1.19.1", |  | ||||||
|     "chokidar": "3.5.2", |     "chokidar": "3.5.2", | ||||||
|     "cls-hooked": "4.2.2", |     "cls-hooked": "4.2.2", | ||||||
|     "commonmark": "0.30.0", |     "commonmark": "0.30.0", | ||||||
| @@ -43,7 +42,7 @@ | |||||||
|     "@electron/remote": "2.0.1", |     "@electron/remote": "2.0.1", | ||||||
|     "express": "4.17.2", |     "express": "4.17.2", | ||||||
|     "express-partial-content": "^1.0.2", |     "express-partial-content": "^1.0.2", | ||||||
|     "express-rate-limit": "6.0.5", |     "express-rate-limit": "6.1.0", | ||||||
|     "express-session": "1.17.2", |     "express-session": "1.17.2", | ||||||
|     "fs-extra": "10.0.0", |     "fs-extra": "10.0.0", | ||||||
|     "helmet": "5.0.1", |     "helmet": "5.0.1", | ||||||
| @@ -83,12 +82,12 @@ | |||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "cross-env": "7.0.3", |     "cross-env": "7.0.3", | ||||||
|     "electron": "16.0.6", |     "electron": "16.0.7", | ||||||
|     "electron-builder": "22.14.5", |     "electron-builder": "22.14.5", | ||||||
|     "electron-packager": "15.4.0", |     "electron-packager": "15.4.0", | ||||||
|     "electron-rebuild": "3.2.6", |     "electron-rebuild": "3.2.7", | ||||||
|     "esm": "3.2.25", |     "esm": "3.2.25", | ||||||
|     "jasmine": "4.0.1", |     "jasmine": "4.0.2", | ||||||
|     "jsdoc": "3.6.7", |     "jsdoc": "3.6.7", | ||||||
|     "lorem-ipsum": "2.0.4", |     "lorem-ipsum": "2.0.4", | ||||||
|     "rcedit": "3.0.1", |     "rcedit": "3.0.1", | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ const express = require('express'); | |||||||
| const path = require('path'); | const path = require('path'); | ||||||
| const favicon = require('serve-favicon'); | const favicon = require('serve-favicon'); | ||||||
| const cookieParser = require('cookie-parser'); | const cookieParser = require('cookie-parser'); | ||||||
| const bodyParser = require('body-parser'); |  | ||||||
| const helmet = require('helmet'); | const helmet = require('helmet'); | ||||||
| const session = require('express-session'); | const session = require('express-session'); | ||||||
| const FileStore = require('session-file-store')(session); | const FileStore = require('session-file-store')(session); | ||||||
| @@ -20,13 +19,13 @@ app.set('views', path.join(__dirname, 'views')); | |||||||
| app.set('view engine', 'ejs'); | app.set('view engine', 'ejs'); | ||||||
|  |  | ||||||
| app.use(helmet({ | app.use(helmet({ | ||||||
|     hidePoweredBy: false, // deactivated because electron 4.0 crashes on this right after startup |     hidePoweredBy: false, // errors out in electron | ||||||
|     contentSecurityPolicy: false |     contentSecurityPolicy: false | ||||||
| })); | })); | ||||||
|  |  | ||||||
| app.use(bodyParser.text({limit: '500mb'})); | app.use(express.text({limit: '500mb'})); | ||||||
| app.use(bodyParser.json({limit: '500mb'})); | app.use(express.json({limit: '500mb'})); | ||||||
| app.use(bodyParser.urlencoded({extended: false})); | app.use(express.urlencoded({extended: false})); | ||||||
| app.use(cookieParser()); | app.use(cookieParser()); | ||||||
| app.use(express.static(path.join(__dirname, 'public'))); | app.use(express.static(path.join(__dirname, 'public'))); | ||||||
| app.use('/libraries', express.static(path.join(__dirname, '..', 'libraries'))); | app.use('/libraries', express.static(path.join(__dirname, '..', 'libraries'))); | ||||||
|   | |||||||
| @@ -2,7 +2,6 @@ | |||||||
|  |  | ||||||
| const sql = require("../services/sql"); | const sql = require("../services/sql"); | ||||||
| const NoteSet = require("../services/search/note_set"); | const NoteSet = require("../services/search/note_set"); | ||||||
| const EtapiToken = require("./entities/etapi_token"); |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Becca is a backend cache of all notes, branches and attributes. There's a similar frontend cache Froca. |  * Becca is a backend cache of all notes, branches and attributes. There's a similar frontend cache Froca. | ||||||
|   | |||||||
| @@ -51,7 +51,7 @@ class Attribute extends AbstractEntity { | |||||||
|         /** @type {int} */ |         /** @type {int} */ | ||||||
|         this.position = position; |         this.position = position; | ||||||
|         /** @type {string} */ |         /** @type {string} */ | ||||||
|         this.value = value; |         this.value = value || ""; | ||||||
|         /** @type {boolean} */ |         /** @type {boolean} */ | ||||||
|         this.isInheritable = !!isInheritable; |         this.isInheritable = !!isInheritable; | ||||||
|         /** @type {string} */ |         /** @type {string} */ | ||||||
|   | |||||||
| @@ -9,6 +9,9 @@ const sql = require("../../services/sql.js"); | |||||||
|  * Used by: |  * Used by: | ||||||
|  * - Trilium Sender |  * - Trilium Sender | ||||||
|  * - ETAPI clients |  * - ETAPI clients | ||||||
|  |  *  | ||||||
|  |  * The format user is presented with is "<etapiTokenId>_<tokenHash>". This is also called "authToken" to distinguish it | ||||||
|  |  * from tokenHash and token. | ||||||
|  */ |  */ | ||||||
| class EtapiToken extends AbstractEntity { | class EtapiToken extends AbstractEntity { | ||||||
|     static get entityName() { return "etapi_tokens"; } |     static get entityName() { return "etapi_tokens"; } | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ const becca = require("../becca/becca"); | |||||||
| const eu = require("./etapi_utils"); | const eu = require("./etapi_utils"); | ||||||
| const mappers = require("./mappers"); | const mappers = require("./mappers"); | ||||||
| const attributeService = require("../services/attributes"); | const attributeService = require("../services/attributes"); | ||||||
| const validators = require("./validators"); | const v = require("./validators"); | ||||||
|  |  | ||||||
| function register(router) { | function register(router) { | ||||||
|     eu.route(router, 'get', '/etapi/attributes/:attributeId', (req, res, next) => { |     eu.route(router, 'get', '/etapi/attributes/:attributeId', (req, res, next) => { | ||||||
| @@ -11,18 +11,23 @@ function register(router) { | |||||||
|         res.json(mappers.mapAttributeToPojo(attribute)); |         res.json(mappers.mapAttributeToPojo(attribute)); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  |     const ALLOWED_PROPERTIES_FOR_CREATE_ATTRIBUTE = { | ||||||
|  |         'attributeId': [v.mandatory, v.notNull, v.isValidEntityId], | ||||||
|  |         'noteId': [v.mandatory, v.notNull, v.isNoteId], | ||||||
|  |         'type': [v.mandatory, v.notNull, v.isAttributeType], | ||||||
|  |         'name': [v.mandatory, v.notNull, v.isString], | ||||||
|  |         'value': [v.notNull, v.isString], | ||||||
|  |         'isInheritable': [v.notNull, v.isBoolean] | ||||||
|  |     }; | ||||||
|  |      | ||||||
|     eu.route(router, 'post' ,'/etapi/attributes', (req, res, next) => { |     eu.route(router, 'post' ,'/etapi/attributes', (req, res, next) => { | ||||||
|         const params = req.body; |         if (req.body.type === 'relation') { | ||||||
|  |             eu.getAndCheckNote(req.body.value); | ||||||
|         eu.getAndCheckNote(params.noteId); |  | ||||||
|  |  | ||||||
|         if (params.type === 'relation') { |  | ||||||
|             eu.getAndCheckNote(params.value); |  | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         if (params.type !== 'relation' && params.type !== 'label') { |         const params = {}; | ||||||
|             throw new eu.EtapiError(400, eu.GENERIC_CODE, `Only "relation" and "label" are supported attribute types, "${params.type}" given.`); |          | ||||||
|         } |         eu.validateAndPatch(params, req.body, ALLOWED_PROPERTIES_FOR_CREATE_ATTRIBUTE); | ||||||
|  |  | ||||||
|         try { |         try { | ||||||
|             const attr = attributeService.createAttribute(params); |             const attr = attributeService.createAttribute(params); | ||||||
| @@ -30,19 +35,25 @@ function register(router) { | |||||||
|             res.json(mappers.mapAttributeToPojo(attr)); |             res.json(mappers.mapAttributeToPojo(attr)); | ||||||
|         } |         } | ||||||
|         catch (e) { |         catch (e) { | ||||||
|             throw new eu.EtapiError(400, eu.GENERIC_CODE, e.message); |             throw new eu.EtapiError(500, eu.GENERIC_CODE, e.message); | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     const ALLOWED_PROPERTIES_FOR_PATCH = { |     const ALLOWED_PROPERTIES_FOR_PATCH = { | ||||||
|         'value': validators.isString |         'value': [v.notNull, v.isString] | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     eu.route(router, 'patch' ,'/etapi/attributes/:attributeId', (req, res, next) => { |     eu.route(router, 'patch' ,'/etapi/attributes/:attributeId', (req, res, next) => { | ||||||
|         const attribute = eu.getAndCheckAttribute(req.params.attributeId); |         const attribute = eu.getAndCheckAttribute(req.params.attributeId); | ||||||
|  |  | ||||||
|  |         if (attribute.type === 'relation') { | ||||||
|  |             eu.getAndCheckNote(req.body.value); | ||||||
|  |         } | ||||||
|  |          | ||||||
|         eu.validateAndPatch(attribute, req.body, ALLOWED_PROPERTIES_FOR_PATCH); |         eu.validateAndPatch(attribute, req.body, ALLOWED_PROPERTIES_FOR_PATCH); | ||||||
|          |          | ||||||
|  |         attribute.save(); | ||||||
|  |  | ||||||
|         res.json(mappers.mapAttributeToPojo(attribute)); |         res.json(mappers.mapAttributeToPojo(attribute)); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ const Branch = require("../becca/entities/branch"); | |||||||
| const noteService = require("../services/notes"); | const noteService = require("../services/notes"); | ||||||
| const TaskContext = require("../services/task_context"); | const TaskContext = require("../services/task_context"); | ||||||
| const entityChangesService = require("../services/entity_changes"); | const entityChangesService = require("../services/entity_changes"); | ||||||
| const validators = require("./validators"); | const v = require("./validators"); | ||||||
|  |  | ||||||
| function register(router) { | function register(router) { | ||||||
|     eu.route(router, 'get', '/etapi/branches/:branchId', (req, res, next) => { |     eu.route(router, 'get', '/etapi/branches/:branchId', (req, res, next) => { | ||||||
| @@ -14,11 +14,19 @@ function register(router) { | |||||||
|         res.json(mappers.mapBranchToPojo(branch)); |         res.json(mappers.mapBranchToPojo(branch)); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     eu.route(router, 'post' ,'/etapi/branches', (req, res, next) => { |     const ALLOWED_PROPERTIES_FOR_CREATE_BRANCH = { | ||||||
|         const params = req.body; |         'branchId': [v.mandatory, v.notNull, v.isValidEntityId], | ||||||
|  |         'noteId': [v.mandatory, v.notNull, v.isNoteId], | ||||||
|  |         'parentNoteId': [v.mandatory, v.notNull, v.isNoteId], | ||||||
|  |         'notePosition': [v.notNull, v.isInteger], | ||||||
|  |         'prefix': [v.isString], | ||||||
|  |         'isExpanded': [v.notNull, v.isBoolean] | ||||||
|  |     }; | ||||||
|      |      | ||||||
|         eu.getAndCheckNote(params.noteId); |     eu.route(router, 'post' ,'/etapi/branches', (req, res, next) => { | ||||||
|         eu.getAndCheckNote(params.parentNoteId); |         const params = {}; | ||||||
|  |          | ||||||
|  |         eu.validateAndPatch(params, req.body, ALLOWED_PROPERTIES_FOR_CREATE_BRANCH); | ||||||
|  |  | ||||||
|         const existing = becca.getBranchFromChildAndParent(params.noteId, params.parentNoteId); |         const existing = becca.getBranchFromChildAndParent(params.noteId, params.parentNoteId); | ||||||
|  |  | ||||||
| @@ -41,15 +49,16 @@ function register(router) { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     const ALLOWED_PROPERTIES_FOR_PATCH = { |     const ALLOWED_PROPERTIES_FOR_PATCH = { | ||||||
|         'notePosition': validators.isInteger, |         'notePosition': [v.notNull, v.isInteger], | ||||||
|         'prefix': validators.isStringOrNull, |         'prefix': [v.isString], | ||||||
|         'isExpanded': validators.isBoolean |         'isExpanded': [v.notNull, v.isBoolean] | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     eu.route(router, 'patch' ,'/etapi/branches/:branchId', (req, res, next) => { |     eu.route(router, 'patch' ,'/etapi/branches/:branchId', (req, res, next) => { | ||||||
|         const branch = eu.getAndCheckBranch(req.params.branchId); |         const branch = eu.getAndCheckBranch(req.params.branchId); | ||||||
|  |  | ||||||
|         eu.validateAndPatch(branch, req.body, ALLOWED_PROPERTIES_FOR_PATCH); |         eu.validateAndPatch(branch, req.body, ALLOWED_PROPERTIES_FOR_PATCH); | ||||||
|  |         branch.save(); | ||||||
|  |  | ||||||
|         res.json(mappers.mapBranchToPojo(branch)); |         res.json(mappers.mapBranchToPojo(branch)); | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -591,13 +591,15 @@ components: | |||||||
|       type: object |       type: object | ||||||
|       required: |       required: | ||||||
|         - parentNoteId |         - parentNoteId | ||||||
|         - type |  | ||||||
|         - title |         - title | ||||||
|  |         - type | ||||||
|         - content |         - content | ||||||
|       properties: |       properties: | ||||||
|         parentNoteId: |         parentNoteId: | ||||||
|           $ref: '#/components/schemas/EntityId' |           $ref: '#/components/schemas/EntityId' | ||||||
|           description: Note ID of the parent note in the tree |           description: Note ID of the parent note in the tree | ||||||
|  |         title: | ||||||
|  |           type: string | ||||||
|         type: |         type: | ||||||
|           type: string |           type: string | ||||||
|           enum:  |           enum:  | ||||||
| @@ -613,8 +615,6 @@ components: | |||||||
|           type: string |           type: string | ||||||
|           description: this needs to be specified only for note types 'code', 'file', 'image'. |           description: this needs to be specified only for note types 'code', 'file', 'image'. | ||||||
|           example: application/json |           example: application/json | ||||||
|         title: |  | ||||||
|           type: string |  | ||||||
|         content: |         content: | ||||||
|           type: string |           type: string | ||||||
|         notePosition: |         notePosition: | ||||||
| @@ -628,6 +628,9 @@ components: | |||||||
|             Prefix is branch (placement) specific title prefix for the note.  |             Prefix is branch (placement) specific title prefix for the note.  | ||||||
|             Let's say you have your note placed into two different places in the tree,  |             Let's say you have your note placed into two different places in the tree,  | ||||||
|             but you want to change the title a bit in one of the placements. For this you can use prefix. |             but you want to change the title a bit in one of the placements. For this you can use prefix. | ||||||
|  |         isExpanded: | ||||||
|  |           type: boolean | ||||||
|  |           description: true if this note (as a folder) should appear expanded | ||||||
|         noteId: |         noteId: | ||||||
|           $ref: '#/components/schemas/EntityId' |           $ref: '#/components/schemas/EntityId' | ||||||
|           description: DON'T specify unless you want to force a specific noteId |           description: DON'T specify unless you want to force a specific noteId | ||||||
| @@ -644,7 +647,7 @@ components: | |||||||
|           type: string |           type: string | ||||||
|         type: |         type: | ||||||
|           type: string |           type: string | ||||||
|           enum: [text, code, book, image, file, mermaid, relation-map, render, search, note-map] |           enum: [text, code, render, file, image, search, relation-map, book, note-map, mermaid] | ||||||
|         mime: |         mime: | ||||||
|           type: string |           type: string | ||||||
|         isProtected: |         isProtected: | ||||||
| @@ -686,7 +689,6 @@ components: | |||||||
|       properties: |       properties: | ||||||
|         branchId: |         branchId: | ||||||
|           $ref: '#/components/schemas/EntityId' |           $ref: '#/components/schemas/EntityId' | ||||||
|           readOnly: true |  | ||||||
|         noteId: |         noteId: | ||||||
|           $ref: '#/components/schemas/EntityId' |           $ref: '#/components/schemas/EntityId' | ||||||
|           readOnly: true |           readOnly: true | ||||||
| @@ -700,7 +702,7 @@ components: | |||||||
|         notePosition: |         notePosition: | ||||||
|           type: integer |           type: integer | ||||||
|           format: int32 |           format: int32 | ||||||
|         isExanded: |         isExpanded: | ||||||
|           type: boolean |           type: boolean | ||||||
|         utcDateModified: |         utcDateModified: | ||||||
|           $ref: '#/components/schemas/UtcDateTime' |           $ref: '#/components/schemas/UtcDateTime' | ||||||
| @@ -713,7 +715,6 @@ components: | |||||||
|       properties: |       properties: | ||||||
|         attributeId: |         attributeId: | ||||||
|           $ref: '#/components/schemas/EntityId' |           $ref: '#/components/schemas/EntityId' | ||||||
|           readOnly: true |  | ||||||
|         noteId: |         noteId: | ||||||
|           $ref: '#/components/schemas/EntityId' |           $ref: '#/components/schemas/EntityId' | ||||||
|           readOnly: true |           readOnly: true | ||||||
| @@ -753,7 +754,7 @@ components: | |||||||
|           description: debugging info on parsing the search query enabled with &debug=true parameter |           description: debugging info on parsing the search query enabled with &debug=true parameter | ||||||
|     EntityId: |     EntityId: | ||||||
|       type: string |       type: string | ||||||
|       pattern: '[a-zA-Z0-9]{4,12}' |       pattern: '[a-zA-Z0-9]{4,32}' | ||||||
|       example: evnnmvHTCgIn |       example: evnnmvHTCgIn | ||||||
|     EntityIdList: |     EntityIdList: | ||||||
|       type: array |       type: array | ||||||
|   | |||||||
| @@ -103,27 +103,26 @@ function getAndCheckAttribute(attributeId) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| function validateAndPatch(entity, props, allowedProperties) { | function validateAndPatch(target, source, allowedProperties) { | ||||||
|     for (const key of Object.keys(props)) { |     for (const key of Object.keys(source)) { | ||||||
|         if (!(key in allowedProperties)) { |         if (!(key in allowedProperties)) { | ||||||
|             throw new EtapiError(400, "PROPERTY_NOT_ALLOWED_FOR_PATCH", `Property '${key}' is not allowed for PATCH.`); |             throw new EtapiError(400, "PROPERTY_NOT_ALLOWED", `Property '${key}' is not allowed for PATCH.`); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             const validator = allowedProperties[key]; |             for (const validator of allowedProperties[key]) { | ||||||
|             const validationResult = validator(props[key]); |                 const validationResult = validator(source[key]); | ||||||
|  |  | ||||||
|                 if (validationResult) { |                 if (validationResult) { | ||||||
|                     throw new EtapiError(400, "PROPERTY_VALIDATION_ERROR", `Validation failed on property '${key}': ${validationResult}`); |                     throw new EtapiError(400, "PROPERTY_VALIDATION_ERROR", `Validation failed on property '${key}': ${validationResult}`); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|      |  | ||||||
|     // validation passed, let's patch |  | ||||||
|     for (const propName of Object.keys(props)) { |  | ||||||
|         entity[propName] = props[propName]; |  | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     entity.save(); |     // validation passed, let's patch | ||||||
|  |     for (const propName of Object.keys(source)) { | ||||||
|  |         target[propName] = source[propName]; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ const eu = require("./etapi_utils"); | |||||||
| const mappers = require("./mappers"); | const mappers = require("./mappers"); | ||||||
| const noteService = require("../services/notes"); | const noteService = require("../services/notes"); | ||||||
| const TaskContext = require("../services/task_context"); | const TaskContext = require("../services/task_context"); | ||||||
| const validators = require("./validators"); | const v = require("./validators"); | ||||||
| const searchService = require("../services/search/services/search"); | const searchService = require("../services/search/services/search"); | ||||||
| const SearchContext = require("../services/search/search_context"); | const SearchContext = require("../services/search/search_context"); | ||||||
|  |  | ||||||
| @@ -39,10 +39,23 @@ function register(router) { | |||||||
|         res.json(mappers.mapNoteToPojo(note)); |         res.json(mappers.mapNoteToPojo(note)); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     eu.route(router, 'post' ,'/etapi/create-note', (req, res, next) => { |     const ALLOWED_PROPERTIES_FOR_CREATE_NOTE = { | ||||||
|         const params = req.body; |         'parentNoteId': [v.mandatory, v.notNull, v.isNoteId], | ||||||
|  |         'title': [v.mandatory, v.notNull, v.isString], | ||||||
|  |         'type': [v.mandatory, v.notNull, v.isNoteType], | ||||||
|  |         'mime': [v.notNull, v.isString], | ||||||
|  |         'content': [v.notNull, v.isString], | ||||||
|  |         'notePosition': [v.notNull, v.isInteger], | ||||||
|  |         'prefix': [v.notNull, v.isInteger], | ||||||
|  |         'isExpanded': [v.notNull, v.isBoolean], | ||||||
|  |         'noteId': [v.notNull, v.isValidEntityId], | ||||||
|  |         'branchId': [v.notNull, v.isValidEntityId], | ||||||
|  |     }; | ||||||
|      |      | ||||||
|         eu.getAndCheckNote(params.parentNoteId); |     eu.route(router, 'post' ,'/etapi/create-note', (req, res, next) => { | ||||||
|  |         const params = {}; | ||||||
|  |          | ||||||
|  |         eu.validateAndPatch(params, req.body, ALLOWED_PROPERTIES_FOR_CREATE_NOTE); | ||||||
|  |  | ||||||
|         try { |         try { | ||||||
|             const resp = noteService.createNewNote(params); |             const resp = noteService.createNewNote(params); | ||||||
| @@ -53,14 +66,14 @@ function register(router) { | |||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|         catch (e) { |         catch (e) { | ||||||
|             return eu.sendError(res, 400, eu.GENERIC_CODE, e.message); |             return eu.sendError(res, 500, eu.GENERIC_CODE, e.message); | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     const ALLOWED_PROPERTIES_FOR_PATCH = { |     const ALLOWED_PROPERTIES_FOR_PATCH = { | ||||||
|         'title': validators.isString, |         'title': [v.notNull, v.isString], | ||||||
|         'type': validators.isString, |         'type': [v.notNull, v.isString], | ||||||
|         'mime': validators.isString |         'mime': [v.notNull, v.isString] | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     eu.route(router, 'patch' ,'/etapi/notes/:noteId', (req, res, next) => { |     eu.route(router, 'patch' ,'/etapi/notes/:noteId', (req, res, next) => { | ||||||
| @@ -71,6 +84,7 @@ function register(router) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         eu.validateAndPatch(note, req.body, ALLOWED_PROPERTIES_FOR_PATCH); |         eu.validateAndPatch(note, req.body, ALLOWED_PROPERTIES_FOR_PATCH); | ||||||
|  |         note.save(); | ||||||
|  |  | ||||||
|         res.json(mappers.mapNoteToPojo(note)); |         res.json(mappers.mapNoteToPojo(note)); | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -1,30 +1,101 @@ | |||||||
|  | const noteTypes = require("../services/note_types"); | ||||||
|  |  | ||||||
|  | function mandatory(obj) { | ||||||
|  |     if (obj === undefined ) { | ||||||
|  |         return `mandatory, but not set`; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function notNull(obj) { | ||||||
|  |     if (obj === null) { | ||||||
|  |         return `cannot be null`; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| function isString(obj) { | function isString(obj) { | ||||||
|  |     if (obj === undefined || obj === null) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |      | ||||||
|     if (typeof obj !== 'string') { |     if (typeof obj !== 'string') { | ||||||
|         return `'${obj}' is not a string`; |         return `'${obj}' is not a string`; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| function isStringOrNull(obj) { |  | ||||||
|     if (obj) { |  | ||||||
|         return isString(obj); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function isBoolean(obj) { | function isBoolean(obj) { | ||||||
|  |     if (obj === undefined || obj === null) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |      | ||||||
|     if (typeof obj !== 'boolean') { |     if (typeof obj !== 'boolean') { | ||||||
|         return `'${obj}' is not a boolean`; |         return `'${obj}' is not a boolean`; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| function isInteger(obj) { | function isInteger(obj) { | ||||||
|  |     if (obj === undefined || obj === null) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |      | ||||||
|     if (!Number.isInteger(obj)) { |     if (!Number.isInteger(obj)) { | ||||||
|         return `'${obj}' is not an integer`; |         return `'${obj}' is not an integer`; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function isNoteId(obj) { | ||||||
|  |     if (obj === undefined || obj === null) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     const becca = require('../becca/becca'); | ||||||
|  |      | ||||||
|  |     if (typeof obj !== 'string') { | ||||||
|  |         return `'${obj}' is not a valid noteId`; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     if (!(obj in becca.notes)) { | ||||||
|  |         return `Note '${obj}' does not exist`; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function isNoteType(obj) { | ||||||
|  |     if (obj === undefined || obj === null) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!noteTypes.includes(obj)) { | ||||||
|  |         return `'${obj}' is not a valid note type, allowed types are: ` + noteTypes.join(", "); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function isAttributeType(obj) { | ||||||
|  |     if (obj === undefined || obj === null) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!['label', 'relation'].includes(obj)) { | ||||||
|  |         return `'${obj}' is not a valid attribute type, allowed types are: label, relation`; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function isValidEntityId(obj) { | ||||||
|  |     if (obj === undefined || obj === null) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     if (typeof obj !== 'string' || !/^[A-Za-z0-9]{4,32}$/.test(obj)) { | ||||||
|  |         return `'${obj}' is not a valid entityId. Only alphanumeric characters are allowed of length 4 to 32.`; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|  |     mandatory, | ||||||
|  |     notNull, | ||||||
|     isString, |     isString, | ||||||
|     isStringOrNull, |  | ||||||
|     isBoolean, |     isBoolean, | ||||||
|     isInteger |     isInteger, | ||||||
|  |     isNoteId, | ||||||
|  |     isNoteType, | ||||||
|  |     isAttributeType, | ||||||
|  |     isValidEntityId | ||||||
| }; | }; | ||||||
| @@ -91,7 +91,7 @@ export default class LoadResults { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         const componentIds = this.noteIdToComponentId[noteId]; |         const componentIds = this.noteIdToComponentId[noteId]; | ||||||
|         return componentIds && !!componentIds.find(sId => sId !== componentId); |         return componentIds && componentIds.find(sId => sId !== componentId) !== undefined; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     addNoteContent(noteId, componentId) { |     addNoteContent(noteId, componentId) { | ||||||
|   | |||||||
							
								
								
									
										0
									
								
								src/public/stylesheets/calendar.css
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								src/public/stylesheets/calendar.css
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @@ -190,7 +190,7 @@ const uploadMiddleware = multer.single('upload'); | |||||||
| function register(app) { | function register(app) { | ||||||
|     route(GET, '/', [auth.checkAuth, csrfMiddleware], indexRoute.index); |     route(GET, '/', [auth.checkAuth, csrfMiddleware], indexRoute.index); | ||||||
|     route(GET, '/login', [auth.checkAppInitialized, auth.checkPasswordSet], loginRoute.loginPage); |     route(GET, '/login', [auth.checkAppInitialized, auth.checkPasswordSet], loginRoute.loginPage); | ||||||
|     route(GET, '/set-password', [auth.checkAppInitialized], loginRoute.setPasswordPage); |     route(GET, '/set-password', [auth.checkAppInitialized, auth.checkPasswordNotSet], loginRoute.setPasswordPage); | ||||||
|  |  | ||||||
|     const loginRateLimiter = rateLimit({ |     const loginRateLimiter = rateLimit({ | ||||||
|         windowMs: 15 * 60 * 1000, // 15 minutes |         windowMs: 15 * 60 * 1000, // 15 minutes | ||||||
| @@ -199,7 +199,7 @@ function register(app) { | |||||||
|  |  | ||||||
|     route(POST, '/login', [loginRateLimiter], loginRoute.login); |     route(POST, '/login', [loginRateLimiter], loginRoute.login); | ||||||
|     route(POST, '/logout', [csrfMiddleware, auth.checkAuth], loginRoute.logout); |     route(POST, '/logout', [csrfMiddleware, auth.checkAuth], loginRoute.logout); | ||||||
|     route(POST, '/set-password', [auth.checkAppInitialized], loginRoute.setPassword); |     route(POST, '/set-password', [auth.checkAppInitialized, auth.checkPasswordNotSet], loginRoute.setPassword); | ||||||
|     route(GET, '/setup', [], setupRoute.setupPage); |     route(GET, '/setup', [], setupRoute.setupPage); | ||||||
|  |  | ||||||
|     apiRoute(GET, '/api/tree', treeApiRoute.getTree); |     apiRoute(GET, '/api/tree', treeApiRoute.getTree); | ||||||
|   | |||||||
| @@ -14,6 +14,8 @@ function setupPage(req, res) { | |||||||
|         else { |         else { | ||||||
|             res.redirect('/'); |             res.redirect('/'); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // we got here because DB is not completely initialized so if schema exists |     // we got here because DB is not completely initialized so if schema exists | ||||||
|   | |||||||
| @@ -15,11 +15,7 @@ function checkAuth(req, res, next) { | |||||||
|         res.redirect("setup"); |         res.redirect("setup"); | ||||||
|     } |     } | ||||||
|     else if (!req.session.loggedIn && !utils.isElectron() && !noAuthentication) { |     else if (!req.session.loggedIn && !utils.isElectron() && !noAuthentication) { | ||||||
|         if (passwordService.isPasswordSet()) { |  | ||||||
|         res.redirect("login"); |         res.redirect("login"); | ||||||
|         } else { |  | ||||||
|             res.redirect("set-password"); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|         next(); |         next(); | ||||||
| @@ -63,6 +59,14 @@ function checkPasswordSet(req, res, next) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function checkPasswordNotSet(req, res, next) { | ||||||
|  |     if (!utils.isElectron() && passwordService.isPasswordSet()) { | ||||||
|  |         res.redirect("login"); | ||||||
|  |     } else { | ||||||
|  |         next(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| function checkAppNotInitialized(req, res, next) { | function checkAppNotInitialized(req, res, next) { | ||||||
|     if (sqlInit.isDbInitialized()) { |     if (sqlInit.isDbInitialized()) { | ||||||
|         reject(req, res, "App already initialized."); |         reject(req, res, "App already initialized."); | ||||||
| @@ -111,6 +115,7 @@ module.exports = { | |||||||
|     checkApiAuth, |     checkApiAuth, | ||||||
|     checkAppInitialized, |     checkAppInitialized, | ||||||
|     checkPasswordSet, |     checkPasswordSet, | ||||||
|  |     checkPasswordNotSet, | ||||||
|     checkAppNotInitialized, |     checkAppNotInitialized, | ||||||
|     checkApiAuthOrElectron, |     checkApiAuthOrElectron, | ||||||
|     checkEtapiToken, |     checkEtapiToken, | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ const attributeService = require('./attributes'); | |||||||
| const noteRevisionService = require('./note_revisions'); | const noteRevisionService = require('./note_revisions'); | ||||||
| const becca = require("../becca/becca"); | const becca = require("../becca/becca"); | ||||||
| const utils = require("../services/utils"); | const utils = require("../services/utils"); | ||||||
|  | const noteTypes = require("../services/note_types"); | ||||||
|  |  | ||||||
| class ConsistencyChecks { | class ConsistencyChecks { | ||||||
|     constructor(autoFix) { |     constructor(autoFix) { | ||||||
| @@ -281,11 +282,13 @@ class ConsistencyChecks { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     findLogicIssues() { |     findLogicIssues() { | ||||||
|  |         const noteTypesStr = noteTypes.map(nt => `'${nt}'`).join(", "); | ||||||
|  |          | ||||||
|         this.findAndFixIssues(` |         this.findAndFixIssues(` | ||||||
|                     SELECT noteId, type |                     SELECT noteId, type | ||||||
|                     FROM notes |                     FROM notes | ||||||
|                     WHERE isDeleted = 0 |                     WHERE isDeleted = 0 | ||||||
|                       AND type NOT IN ('text', 'code', 'render', 'file', 'image', 'search', 'relation-map', 'book', 'note-map', 'mermaid')`, |                       AND type NOT IN (${noteTypesStr})`, | ||||||
|             ({noteId, type}) => { |             ({noteId, type}) => { | ||||||
|                 if (this.autoFix) { |                 if (this.autoFix) { | ||||||
|                     const note = becca.getNote(noteId); |                     const note = becca.getNote(noteId); | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ function addEntityChange(origEntityChange) { | |||||||
|         ec.changeId = utils.randomString(12); |         ec.changeId = utils.randomString(12); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ec.componentId = ec.componentId || cls.getComponentId() || ""; |     ec.componentId = ec.componentId || cls.getComponentId() || "NA"; // NA = not available | ||||||
|     ec.instanceId = ec.instanceId || instanceId; |     ec.instanceId = ec.instanceId || instanceId; | ||||||
|     ec.isSynced = ec.isSynced ? 1 : 0; |     ec.isSynced = ec.isSynced ? 1 : 0; | ||||||
|     ec.isErased = ec.isErased ? 1 : 0; |     ec.isErased = ec.isErased ? 1 : 0; | ||||||
| @@ -43,7 +43,7 @@ function addNoteReorderingEntityChange(parentNoteId, componentId) { | |||||||
|         utcDateChanged: dateUtils.utcNowDateTime(), |         utcDateChanged: dateUtils.utcNowDateTime(), | ||||||
|         isSynced: true, |         isSynced: true, | ||||||
|         componentId, |         componentId, | ||||||
|         instanceId: instanceId |         instanceId | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     const eventService = require('./events'); |     const eventService = require('./events'); | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ function getTokenHash(token) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function createToken(tokenName) { | function createToken(tokenName) { | ||||||
|     const token = utils.randomSecureToken(); |     const token = utils.randomSecureToken(32); | ||||||
|     const tokenHash = getTokenHash(token); |     const tokenHash = getTokenHash(token); | ||||||
|  |  | ||||||
|     const etapiToken = new EtapiToken({ |     const etapiToken = new EtapiToken({ | ||||||
|   | |||||||
| @@ -18,8 +18,6 @@ const Branch = require('../becca/entities/branch'); | |||||||
| const Note = require('../becca/entities/note'); | const Note = require('../becca/entities/note'); | ||||||
| const Attribute = require('../becca/entities/attribute'); | const Attribute = require('../becca/entities/attribute'); | ||||||
|  |  | ||||||
| // TODO: patch/put note content |  | ||||||
|  |  | ||||||
| function getNewNotePosition(parentNoteId) { | function getNewNotePosition(parentNoteId) { | ||||||
|     const note = becca.notes[parentNoteId]; |     const note = becca.notes[parentNoteId]; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,22 +1,27 @@ | |||||||
| const becca = require('../becca/becca'); | const becca = require('../becca/becca'); | ||||||
| const sql = require("./sql"); | const sql = require("./sql"); | ||||||
|  |  | ||||||
| function getOption(name) { | function getOptionOrNull(name) { | ||||||
|     let option; |     let option; | ||||||
|  |  | ||||||
|     if (becca.loaded) { |     if (becca.loaded) { | ||||||
|         option = becca.getOption(name); |         option = becca.getOption(name); | ||||||
|     } |     } else { | ||||||
|     else { |  | ||||||
|         // e.g. in initial sync becca is not loaded because DB is not initialized |         // e.g. in initial sync becca is not loaded because DB is not initialized | ||||||
|         option = sql.getRow("SELECT * FROM options WHERE name = ?", name); |         option = sql.getRow("SELECT * FROM options WHERE name = ?", name); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     if (!option) { |     return option ? option.value : null; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function getOption(name) { | ||||||
|  |     const val = getOptionOrNull(name); | ||||||
|  |  | ||||||
|  |     if (val === null) { | ||||||
|         throw new Error(`Option "${name}" doesn't exist`); |         throw new Error(`Option "${name}" doesn't exist`); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return option.value; |     return val; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -96,5 +101,6 @@ module.exports = { | |||||||
|     setOption, |     setOption, | ||||||
|     createOption, |     createOption, | ||||||
|     getOptions, |     getOptions, | ||||||
|     getOptionsMap |     getOptionsMap, | ||||||
|  |     getOptionOrNull | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -6,7 +6,11 @@ const dataEncryptionService = require('./data_encryption'); | |||||||
| function verifyPassword(password) { | function verifyPassword(password) { | ||||||
|     const givenPasswordHash = utils.toBase64(myScryptService.getVerificationHash(password)); |     const givenPasswordHash = utils.toBase64(myScryptService.getVerificationHash(password)); | ||||||
|  |  | ||||||
|     const dbPasswordHash = optionService.getOption('passwordVerificationHash'); |     const dbPasswordHash = optionService.getOptionOrNull('passwordVerificationHash'); | ||||||
|  |  | ||||||
|  |     if (!dbPasswordHash) { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|      |      | ||||||
|     return givenPasswordHash === dbPasswordHash; |     return givenPasswordHash === dbPasswordHash; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -154,10 +154,6 @@ function sortNotes(parentNoteId, customSortBy = 'title', reverse = false, folder | |||||||
|             const topAEl = fetchValue(a, 'top'); |             const topAEl = fetchValue(a, 'top'); | ||||||
|             const topBEl = fetchValue(b, 'top'); |             const topBEl = fetchValue(b, 'top'); | ||||||
|  |  | ||||||
|             console.log(a.title, topAEl); |  | ||||||
|             console.log(b.title, topBEl); |  | ||||||
|             console.log("comp", compare(topAEl, topBEl) && !reverse); |  | ||||||
|  |  | ||||||
|             if (topAEl !== topBEl) { |             if (topAEl !== topBEl) { | ||||||
|                 // since "top" should not be reversible, we'll reverse it once more to nullify this effect |                 // since "top" should not be reversible, we'll reverse it once more to nullify this effect | ||||||
|                 return compare(topAEl, topBEl) * (reverse ? -1 : 1); |                 return compare(topAEl, topBEl) * (reverse ? -1 : 1); | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ Content-Type: application/json | |||||||
| } | } | ||||||
|  |  | ||||||
| > {% | > {% | ||||||
|     client.assert(response.status === 200, "Response status is not 200"); |     client.assert(response.status === 200); | ||||||
|      |      | ||||||
|     client.global.set("authToken", response.body.authToken); |     client.global.set("authToken", response.body.authToken); | ||||||
| %} | %} | ||||||
| @@ -3,6 +3,8 @@ Authorization: {{authToken}} | |||||||
| Content-Type: application/json | Content-Type: application/json | ||||||
|  |  | ||||||
| { | { | ||||||
|  |   "noteId": "forcedId{{$randomInt}}", | ||||||
|  |   "branchId": "forcedId{{$randomInt}}", | ||||||
|   "parentNoteId": "root", |   "parentNoteId": "root", | ||||||
|   "title": "Hello", |   "title": "Hello", | ||||||
|   "type": "text", |   "type": "text", | ||||||
| @@ -10,11 +12,11 @@ Content-Type: application/json | |||||||
| } | } | ||||||
|  |  | ||||||
| > {%     | > {%     | ||||||
|     client.test("Request executed successfully", function() { |     client.assert(response.status === 200); | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |     client.assert(response.body.note.noteId.startsWith("forcedId")); | ||||||
|     client.assert(response.body.note.title == "Hello"); |     client.assert(response.body.note.title == "Hello"); | ||||||
|  |     client.assert(response.body.branch.branchId.startsWith("forcedId")); | ||||||
|     client.assert(response.body.branch.parentNoteId == "root"); |     client.assert(response.body.branch.parentNoteId == "root"); | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     client.log(`Created note ` + response.body.note.noteId + ` and branch ` + response.body.branch.branchId); |     client.log(`Created note ` + response.body.note.noteId + ` and branch ` + response.body.branch.branchId); | ||||||
|      |      | ||||||
| @@ -29,15 +31,14 @@ Authorization: {{authToken}} | |||||||
| Content-Type: application/json | Content-Type: application/json | ||||||
|  |  | ||||||
| { | { | ||||||
|  |   "branchId": "forcedClonedId", | ||||||
|   "noteId": "{{createdNoteId}}", |   "noteId": "{{createdNoteId}}", | ||||||
|   "parentNoteId": "hidden" |   "parentNoteId": "hidden" | ||||||
| } | } | ||||||
|  |  | ||||||
| > {% | > {% | ||||||
|     client.test("Request executed successfully", function() { |     client.assert(response.status === 200); | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |  | ||||||
|     client.assert(response.body.parentNoteId == "hidden"); |     client.assert(response.body.parentNoteId == "hidden"); | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     client.global.set("clonedBranchId", response.body.branchId); |     client.global.set("clonedBranchId", response.body.branchId); | ||||||
|      |      | ||||||
| @@ -50,14 +51,12 @@ GET {{triliumHost}}/etapi/notes/{{createdNoteId}} | |||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% | ||||||
|     client.test("Request executed successfully", function() { |     client.assert(response.status === 200); | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |  | ||||||
|     client.assert(response.body.noteId == client.global.get("createdNoteId")); |     client.assert(response.body.noteId == client.global.get("createdNoteId")); | ||||||
|     client.assert(response.body.title == "Hello"); |     client.assert(response.body.title == "Hello"); | ||||||
|     // order is not defined and may fail in the future |     // order is not defined and may fail in the future | ||||||
|     client.assert(response.body.parentBranchIds[0] == client.global.get("clonedBranchId")) |     client.assert(response.body.parentBranchIds[0] == client.global.get("clonedBranchId")) | ||||||
|     client.assert(response.body.parentBranchIds[1] == client.global.get("createdBranchId")); |     client.assert(response.body.parentBranchIds[1] == client.global.get("createdBranchId")); | ||||||
|     }); |  | ||||||
| %} | %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
| @@ -66,10 +65,8 @@ GET {{triliumHost}}/etapi/notes/{{createdNoteId}}/content | |||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% | ||||||
|     client.test("Request executed successfully", function() { |     client.assert(response.status === 200); | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |  | ||||||
|     client.assert(response.body == "Hi there!"); |     client.assert(response.body == "Hi there!"); | ||||||
|     }); |  | ||||||
| %} | %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
| @@ -78,11 +75,9 @@ GET {{triliumHost}}/etapi/branches/{{createdBranchId}} | |||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% | ||||||
|     client.test("Request executed successfully", function() { |     client.assert(response.status === 200); | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |  | ||||||
|     client.assert(response.body.branchId == client.global.get("createdBranchId")); |     client.assert(response.body.branchId == client.global.get("createdBranchId")); | ||||||
|     client.assert(response.body.parentNoteId == "root"); |     client.assert(response.body.parentNoteId == "root"); | ||||||
|     }); |  | ||||||
| %} | %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
| @@ -91,11 +86,9 @@ GET {{triliumHost}}/etapi/branches/{{clonedBranchId}} | |||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% | ||||||
|     client.test("Request executed successfully", function() { |     client.assert(response.status === 200); | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |  | ||||||
|     client.assert(response.body.branchId == client.global.get("clonedBranchId")); |     client.assert(response.body.branchId == client.global.get("clonedBranchId")); | ||||||
|     client.assert(response.body.parentNoteId == "hidden"); |     client.assert(response.body.parentNoteId == "hidden"); | ||||||
|     }); |  | ||||||
| %} | %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
| @@ -105,19 +98,17 @@ Content-Type: application/json | |||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| { | { | ||||||
|  |   "attributeId": "forcedAttributeId{{$randomInt}}", | ||||||
|   "noteId": "{{createdNoteId}}", |   "noteId": "{{createdNoteId}}", | ||||||
|   "type": "label", |   "type": "label", | ||||||
|   "name": "mylabel", |   "name": "mylabel", | ||||||
|   "value": "val", |   "value": "val", | ||||||
|   "isInheritable": "true" |   "isInheritable": true | ||||||
| } | } | ||||||
|  |  | ||||||
| > {% | > {% | ||||||
|     client.test("Request executed successfully", function() { |     client.assert(response.status === 200); | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |     client.assert(response.body.attributeId.startsWith("forcedAttributeId")); | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     client.log(`Created attribute ` + response.body.attributeId); |  | ||||||
|      |      | ||||||
|     client.global.set("createdAttributeId", response.body.attributeId); |     client.global.set("createdAttributeId", response.body.attributeId); | ||||||
| %} | %} | ||||||
| @@ -128,8 +119,6 @@ GET {{triliumHost}}/etapi/attributes/{{createdAttributeId}} | |||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% | ||||||
|     client.test("Request executed successfully", function() { |     client.assert(response.status === 200); | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |  | ||||||
|     client.assert(response.body.attributeId == client.global.get("createdAttributeId")); |     client.assert(response.body.attributeId == client.global.get("createdAttributeId")); | ||||||
|     }); |  | ||||||
| %} | %} | ||||||
| @@ -25,7 +25,7 @@ Content-Type: application/json | |||||||
|   "type": "label", |   "type": "label", | ||||||
|   "name": "mylabel", |   "name": "mylabel", | ||||||
|   "value": "val", |   "value": "val", | ||||||
|   "isInheritable": "true" |   "isInheritable": true | ||||||
| } | } | ||||||
|  |  | ||||||
| > {% client.global.set("createdAttributeId", response.body.attributeId); %} | > {% client.global.set("createdAttributeId", response.body.attributeId); %} | ||||||
| @@ -35,14 +35,14 @@ Content-Type: application/json | |||||||
| GET {{triliumHost}}/etapi/notes/{{createdNoteId}} | GET {{triliumHost}}/etapi/notes/{{createdNoteId}} | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% client.assert(response.status === 200, "Response status is not 200"); %} | > {% client.assert(response.status === 200); %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| GET {{triliumHost}}/etapi/branches/{{createdBranchId}} | GET {{triliumHost}}/etapi/branches/{{createdBranchId}} | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% client.assert(response.status === 200, "Response status is not 200"); %} | > {% client.assert(response.status === 200); %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
|   | |||||||
| @@ -32,21 +32,21 @@ Content-Type: application/json | |||||||
| GET {{triliumHost}}/etapi/notes/{{createdNoteId}} | GET {{triliumHost}}/etapi/notes/{{createdNoteId}} | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% client.assert(response.status === 200, "Response status is not 200"); %} | > {% client.assert(response.status === 200); %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| GET {{triliumHost}}/etapi/branches/{{createdBranchId}} | GET {{triliumHost}}/etapi/branches/{{createdBranchId}} | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% client.assert(response.status === 200, "Response status is not 200"); %} | > {% client.assert(response.status === 200); %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| GET {{triliumHost}}/etapi/branches/{{clonedBranchId}} | GET {{triliumHost}}/etapi/branches/{{clonedBranchId}} | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% client.assert(response.status === 200, "Response status is not 200"); %} | > {% client.assert(response.status === 200); %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| @@ -77,11 +77,11 @@ Authorization: {{authToken}} | |||||||
| GET {{triliumHost}}/etapi/branches/{{clonedBranchId}} | GET {{triliumHost}}/etapi/branches/{{clonedBranchId}} | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% client.assert(response.status === 200, "Response status is not 200"); %} | > {% client.assert(response.status === 200); %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| GET {{triliumHost}}/etapi/notes/{{createdNoteId}} | GET {{triliumHost}}/etapi/notes/{{createdNoteId}} | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% client.assert(response.status === 200, "Response status is not 200"); %} | > {% client.assert(response.status === 200); %} | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ Content-Type: application/json | |||||||
|   "type": "label", |   "type": "label", | ||||||
|   "name": "mylabel", |   "name": "mylabel", | ||||||
|   "value": "val", |   "value": "val", | ||||||
|   "isInheritable": "true" |   "isInheritable": true | ||||||
| } | } | ||||||
|  |  | ||||||
| > {% client.global.set("createdAttributeId", response.body.attributeId); %} | > {% client.global.set("createdAttributeId", response.body.attributeId); %} | ||||||
| @@ -48,28 +48,28 @@ Content-Type: application/json | |||||||
| GET {{triliumHost}}/etapi/notes/{{createdNoteId}} | GET {{triliumHost}}/etapi/notes/{{createdNoteId}} | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% client.assert(response.status === 200, "Response status is not 200"); %} | > {% client.assert(response.status === 200); %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| GET {{triliumHost}}/etapi/branches/{{createdBranchId}} | GET {{triliumHost}}/etapi/branches/{{createdBranchId}} | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% client.assert(response.status === 200, "Response status is not 200"); %} | > {% client.assert(response.status === 200); %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| GET {{triliumHost}}/etapi/branches/{{clonedBranchId}} | GET {{triliumHost}}/etapi/branches/{{clonedBranchId}} | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% client.assert(response.status === 200, "Response status is not 200"); %} | > {% client.assert(response.status === 200); %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| GET {{triliumHost}}/etapi/attributes/{{createdAttributeId}} | GET {{triliumHost}}/etapi/attributes/{{createdAttributeId}} | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% client.assert(response.status === 200, "Response status is not 200"); %} | > {% client.assert(response.status === 200); %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,22 +1,14 @@ | |||||||
| GET {{triliumHost}}/etapi/inbox/2022-01-01 | GET {{triliumHost}}/etapi/inbox/2022-01-01 | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% client.assert(response.status === 200); %} | ||||||
|     client.test("Request executed successfully", function() { |  | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |  | ||||||
|     }); |  | ||||||
| %} |  | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| GET {{triliumHost}}/etapi/calendar/days/2022-01-01 | GET {{triliumHost}}/etapi/calendar/days/2022-01-01 | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% client.assert(response.status === 200); %} | ||||||
|     client.test("Request executed successfully", function() { |  | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |  | ||||||
|     }); |  | ||||||
| %} |  | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| @@ -24,10 +16,8 @@ GET {{triliumHost}}/etapi/calendar/days/2022-1 | |||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% | ||||||
|     client.test("Correct error handling", function() { |     client.assert(response.status === 400); | ||||||
|         client.assert(response.status === 400, "Response status is not 400"); |  | ||||||
|     client.assert(response.body.code === "DATE_INVALID"); |     client.assert(response.body.code === "DATE_INVALID"); | ||||||
|     }); |  | ||||||
| %} | %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
| @@ -35,11 +25,7 @@ Authorization: {{authToken}} | |||||||
| GET {{triliumHost}}/etapi/calendar/weeks/2022-01-01 | GET {{triliumHost}}/etapi/calendar/weeks/2022-01-01 | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% client.assert(response.status === 200); %} | ||||||
|     client.test("Request executed successfully", function() { |  | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |  | ||||||
|     }); |  | ||||||
| %} |  | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| @@ -47,10 +33,8 @@ GET {{triliumHost}}/etapi/calendar/weeks/2022-1 | |||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% | ||||||
|     client.test("Correct error handling", function() { |     client.assert(response.status === 400); | ||||||
|         client.assert(response.status === 400, "Response status is not 400"); |  | ||||||
|     client.assert(response.body.code === "DATE_INVALID"); |     client.assert(response.body.code === "DATE_INVALID"); | ||||||
|     }); |  | ||||||
| %} | %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
| @@ -58,11 +42,7 @@ Authorization: {{authToken}} | |||||||
| GET {{triliumHost}}/etapi/calendar/months/2022-01 | GET {{triliumHost}}/etapi/calendar/months/2022-01 | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% client.assert(response.status === 200); %} | ||||||
|     client.test("Request executed successfully", function() { |  | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |  | ||||||
|     }); |  | ||||||
| %} |  | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| @@ -70,10 +50,8 @@ GET {{triliumHost}}/etapi/calendar/months/2022-1 | |||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% | ||||||
|     client.test("Correct error handling", function() { |     client.assert(response.status === 400); | ||||||
|         client.assert(response.status === 400, "Response status is not 400"); |  | ||||||
|     client.assert(response.body.code === "MONTH_INVALID"); |     client.assert(response.body.code === "MONTH_INVALID"); | ||||||
|     }); |  | ||||||
| %} | %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
| @@ -81,11 +59,7 @@ Authorization: {{authToken}} | |||||||
| GET {{triliumHost}}/etapi/calendar/years/2022 | GET {{triliumHost}}/etapi/calendar/years/2022 | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% client.assert(response.status === 200); %} | ||||||
|     client.test("Request executed successfully", function() { |  | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |  | ||||||
|     }); |  | ||||||
| %} |  | ||||||
|  |  | ||||||
| ### | ### | ||||||
|  |  | ||||||
| @@ -93,11 +67,6 @@ GET {{triliumHost}}/etapi/calendar/years/202 | |||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% | ||||||
|     client.test("Correct error handling", function() { |     client.assert(response.status === 400); | ||||||
|         client.assert(response.status === 400, "Response status is not 400"); |  | ||||||
|     client.assert(response.body.code === "YEAR_INVALID"); |     client.assert(response.body.code === "YEAR_INVALID"); | ||||||
|     }); |  | ||||||
| %} | %} | ||||||
|  |  | ||||||
| ### |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,8 +1,4 @@ | |||||||
| POST {{triliumHost}}/etapi/refresh-note-ordering/root | POST {{triliumHost}}/etapi/refresh-note-ordering/root | ||||||
| Authorization: {{authToken}} | Authorization: {{authToken}} | ||||||
|  |  | ||||||
| > {% | > {% client.assert(response.status === 200); %} | ||||||
|     client.test("Request executed successfully", function() { |  | ||||||
|         client.assert(response.status === 200, "Response status is not 200"); |  | ||||||
|     }); |  | ||||||
| %} |  | ||||||
| @@ -25,7 +25,7 @@ Content-Type: application/json | |||||||
|   "type": "label", |   "type": "label", | ||||||
|   "name": "mylabel", |   "name": "mylabel", | ||||||
|   "value": "val", |   "value": "val", | ||||||
|   "isInheritable": "true" |   "isInheritable": true | ||||||
| } | } | ||||||
|  |  | ||||||
| > {% client.global.set("createdAttributeId", response.body.attributeId); %} | > {% client.global.set("createdAttributeId", response.body.attributeId); %} | ||||||
| @@ -61,7 +61,7 @@ Content-Type: application/json | |||||||
|  |  | ||||||
| > {%  | > {%  | ||||||
|     client.assert(response.status === 400);  |     client.assert(response.status === 400);  | ||||||
|     client.assert(response.body.code == "PROPERTY_NOT_ALLOWED_FOR_PATCH"); |     client.assert(response.body.code == "PROPERTY_NOT_ALLOWED"); | ||||||
| %} | %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ Content-Type: application/json | |||||||
|  |  | ||||||
| > {%  | > {%  | ||||||
|     client.assert(response.status === 400);  |     client.assert(response.status === 400);  | ||||||
|     client.assert(response.body.code == "PROPERTY_NOT_ALLOWED_FOR_PATCH"); |     client.assert(response.body.code == "PROPERTY_NOT_ALLOWED"); | ||||||
| %} | %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|   | |||||||
| @@ -60,7 +60,7 @@ Content-Type: application/json | |||||||
|  |  | ||||||
| > {%  | > {%  | ||||||
|     client.assert(response.status === 400);  |     client.assert(response.status === 400);  | ||||||
|     client.assert(response.body.code == "PROPERTY_NOT_ALLOWED_FOR_PATCH"); |     client.assert(response.body.code == "PROPERTY_NOT_ALLOWED"); | ||||||
| %} | %} | ||||||
|  |  | ||||||
| ### | ### | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user