From ef711af5b552d6719af8cb668d7cfe1db7a32e23 Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Thu, 27 Sep 2018 18:35:10 +0000 Subject: [PATCH] Api: Added method to get notes --- CliClient/package-lock.json | 272 ++++++++++++++++----- CliClient/package.json | 2 +- CliClient/tests/services_rest_Api.js | 44 ++++ ReactNativeClient/lib/fs-driver-node.js | 6 +- ReactNativeClient/lib/models/Note.js | 10 +- ReactNativeClient/lib/services/rest/Api.js | 66 ++++- ReactNativeClient/lib/shim-init-node.js | 1 + 7 files changed, 322 insertions(+), 79 deletions(-) diff --git a/CliClient/package-lock.json b/CliClient/package-lock.json index e9dd15e69..adef06181 100644 --- a/CliClient/package-lock.json +++ b/CliClient/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "abab": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", - "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==" }, "abbrev": { "version": "1.1.1", @@ -15,18 +15,31 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "acorn": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", - "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" }, "acorn-globals": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.1.0.tgz", - "integrity": "sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", + "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", "requires": { - "acorn": "^5.0.0" + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.2.tgz", + "integrity": "sha512-GXmKIvbrN3TV7aVqAzVFaMW8F8wzVX7voEBRO3bDA64+EX37YSayggRJP5Xig6HYHBkWKpFg9W5gg6orklubhg==" + } } }, + "acorn-walk": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.0.1.tgz", + "integrity": "sha512-PqVQ8c6a3kyqdsUZlC7nljp3FFuxipBRHKu+7C1h8QygBFlzTaDX5HD383jej3Peed+1aDG8HwkfB1Z1HMNPkw==" + }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", @@ -237,9 +250,9 @@ } }, "browser-process-hrtime": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz", - "integrity": "sha1-Ql1opY00R/AqBKqJQYf86K+Le44=" + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==" }, "buffer-alloc": { "version": "1.2.0", @@ -441,14 +454,14 @@ } }, "cssom": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.3.tgz", - "integrity": "sha512-pjE/I/NSp3iyeoxXN5QaoJpgzYUMj2dJHx9OSufoTliJLDx+kuOQaMCJW8OwvrKJswhXUHnHN6eUmUSETN0msg==" + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", + "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==" }, "cssstyle": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.3.1.tgz", - "integrity": "sha512-tNvaxM5blOnxanyxI6panOsnfiyLRj3HV4qjqqS45WPNS1usdYWRUQjqTEEELK73lpeP/1KoIGYUwrBn/VcECA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz", + "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==", "requires": { "cssom": "0.3.x" } @@ -475,13 +488,25 @@ "integrity": "sha1-GK6XmmoMqZSwYlhTkW0mYruuCxo=" }, "data-urls": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.0.tgz", - "integrity": "sha512-ai40PPQR0Fn1lD2PPie79CibnlMN2AYiDhwFX/rZHVsxbs5kNJSjegqXIprhouGXlRdEnfybva7kqRGnB6mypA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.1.tgz", + "integrity": "sha512-0HdcMZzK6ubMUnsMmQmG0AcLQPvbvb47R0+7CCZQCYgcd8OUWG91CG7sM6GoXgjz+WLl4ArFzHtBMy/QqSF4eg==", "requires": { - "abab": "^1.0.4", - "whatwg-mimetype": "^2.0.0", - "whatwg-url": "^6.4.0" + "abab": "^2.0.0", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } } }, "debug": { @@ -626,9 +651,9 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.10.0.tgz", - "integrity": "sha512-fjUOf8johsv23WuIKdNQU4P9t9jhQ4Qzx6pC2uW890OloK3Zs1ZAoCNpg/2larNF501jLl3UNy0kIRcF6VI22g==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", + "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", "requires": { "esprima": "^3.1.3", "estraverse": "^4.2.0", @@ -1397,9 +1422,9 @@ "dev": true }, "joplin-turndown": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.8.tgz", - "integrity": "sha512-RPZJSZEplVPL3UiJNkaKsFAG8bCGofsKIiH24s8/4qcy1xYnEufvg++rHm7rxi/0VCtpSkRBlWHSs1/srJZvoA==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.9.tgz", + "integrity": "sha512-8MOxX4t5Ai22muHhXPMGNoKc/AB7gSo0eUvNh6dyd6b3vcSiMIRZE8UHpMjS9ruJQ+8e+8TtJXc0nfbexeHwrA==", "requires": { "jsdom": "^11.9.0" } @@ -1426,36 +1451,151 @@ "optional": true }, "jsdom": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.11.0.tgz", - "integrity": "sha512-ou1VyfjwsSuWkudGxb03FotDajxAto6USAlmMZjE2lc0jCznt7sBWkhfRBRaWwbnmDqdMSTKTLT5d9sBFkkM7A==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", "requires": { - "abab": "^1.0.4", - "acorn": "^5.3.0", + "abab": "^2.0.0", + "acorn": "^5.5.3", "acorn-globals": "^4.1.0", "array-equal": "^1.0.0", "cssom": ">= 0.3.2 < 0.4.0", - "cssstyle": ">= 0.3.1 < 0.4.0", + "cssstyle": "^1.0.0", "data-urls": "^1.0.0", - "domexception": "^1.0.0", - "escodegen": "^1.9.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", "html-encoding-sniffer": "^1.0.2", - "left-pad": "^1.2.0", - "nwsapi": "^2.0.0", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", "parse5": "4.0.0", "pn": "^1.1.0", - "request": "^2.83.0", + "request": "^2.87.0", "request-promise-native": "^1.0.5", "sax": "^1.2.4", "symbol-tree": "^3.2.2", - "tough-cookie": "^2.3.3", + "tough-cookie": "^2.3.4", "w3c-hr-time": "^1.0.1", "webidl-conversions": "^4.0.2", "whatwg-encoding": "^1.0.3", "whatwg-mimetype": "^2.1.0", "whatwg-url": "^6.4.1", - "ws": "^4.0.0", + "ws": "^5.2.0", "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.6", + "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "~1.0.0" + } + } + } + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "requires": { + "ajv": "^5.3.0", + "har-schema": "^2.0.0" + } + }, + "mime-db": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" + }, + "mime-types": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", + "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "requires": { + "mime-db": "~1.36.0" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } } }, "json-schema": { @@ -1851,9 +1991,9 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "nwsapi": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.4.tgz", - "integrity": "sha512-Zt6HRR6RcJkuj5/N9zeE7FN6YitRW//hK2wTOwX274IBphbY3Zf5+yn5mZ9v/SzAOTMjQNxZf9KkmPLWn0cV4g==" + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.9.tgz", + "integrity": "sha512-nlWFSCTYQcHk/6A9FFnfhKc14c3aFhfdNBXgo8Qgi9QTBu/qg3Ww+Uiz9wMzXd1T8GFxPc2QIHB6Qtf2XFryFQ==" }, "oauth-sign": { "version": "0.8.2", @@ -2261,6 +2401,11 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", @@ -2813,17 +2958,27 @@ "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" }, "whatwg-encoding": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz", - "integrity": "sha512-jLBwwKUhi8WtBfsMQlL4bUUcT8sMkAtQinscJAe/M4KHCkHuUJAF6vuB0tueNIw4c8ziO6AkRmgY+jL3a0iiPw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.4.tgz", + "integrity": "sha512-vM9KWN6MP2mIHZ86ytcyIv7e8Cj3KTfO2nd2c8PFDqcI4bxFmQp83ibq4wadq7rL9l9sZV6o9B0LTt8ygGAAXg==", "requires": { - "iconv-lite": "0.4.19" + "iconv-lite": "0.4.23" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } } }, "whatwg-mimetype": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz", - "integrity": "sha512-FKxhYLytBQiUKjkYteN71fAUA3g6KpNXoho1isLiLSB3N1G4F35Q5vUxWfKFhBwi5IWF27VE6WxhrnnC+m0Mew==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.2.0.tgz", + "integrity": "sha512-5YSO1nMd5D1hY3WzAQV3PzZL83W3YeyR1yW9PcH26Weh1t+Vzh9B6XkDh7aXm83HBZ4nSMvkjvN2H2ySWIvBgw==" }, "whatwg-url": { "version": "6.5.0", @@ -2882,12 +3037,11 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz", - "integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0" + "async-limiter": "~1.0.0" } }, "xml-name-validator": { diff --git a/CliClient/package.json b/CliClient/package.json index 2af3adfef..498cf893d 100644 --- a/CliClient/package.json +++ b/CliClient/package.json @@ -39,7 +39,7 @@ "html-minifier": "^3.5.15", "image-data-uri": "^2.0.0", "image-type": "^3.0.0", - "joplin-turndown": "^4.0.8", + "joplin-turndown": "^4.0.9", "joplin-turndown-plugin-gfm": "^1.0.7", "jssha": "^2.3.0", "levenshtein": "^1.0.5", diff --git a/CliClient/tests/services_rest_Api.js b/CliClient/tests/services_rest_Api.js index 467657afb..a9c70eff4 100644 --- a/CliClient/tests/services_rest_Api.js +++ b/CliClient/tests/services_rest_Api.js @@ -5,8 +5,11 @@ const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synch const markdownUtils = require('lib/markdownUtils.js'); const Api = require('lib/services/rest/Api'); const Folder = require('lib/models/Folder'); +const Note = require('lib/models/Note'); const Resource = require('lib/models/Resource'); +jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; + process.on('unhandledRejection', (reason, p) => { console.log('Unhandled Rejection at: Promise', p, 'reason:', reason); }); @@ -42,6 +45,35 @@ describe('services_rest_Api', function() { done(); }); + it('should get notes', async (done) => { + let response = null; + const f1 = await Folder.save({ title: "mon carnet" }); + const f2 = await Folder.save({ title: "mon deuxième carnet" }); + const n1 = await Note.save({ title: 'un', parent_id: f1.id }); + const n2 = await Note.save({ title: 'deux', parent_id: f1.id }); + const n3 = await Note.save({ title: 'trois', parent_id: f2.id }); + + response = await api.route('GET', 'notes'); + expect(response.length).toBe(3); + + response = await api.route('GET', 'notes', { parent_id: f1.id }); + expect(response.length).toBe(2); + + response = await api.route('GET', 'notes', { parent_id: f2.id }); + expect(response.length).toBe(1); + expect(response[0].id).toBe(n3.id); + + response = await api.route('GET', 'notes/' + n1.id); + expect(response.id).toBe(n1.id); + + response = await api.route('GET', 'notes/' + n3.id, { fields: 'id,title' }); + expect(Object.getOwnPropertyNames(response).length).toBe(3); + expect(response.id).toBe(n3.id); + expect(response.title).toBe('trois'); + + done(); + }); + it('should create notes', async (done) => { let response = null; const f = await Folder.save({ title: "mon carnet" }); @@ -115,4 +147,16 @@ describe('services_rest_Api', function() { done(); }); + it('should handle tokens', async (done) => { + api = new Api('mytoken'); + + const hasThrown = await checkThrowAsync(async () => await api.route('GET', 'notes')); + expect(hasThrown).toBe(true); + + const response = await api.route('GET', 'notes', { token: 'mytoken' }) + expect(response.length).toBe(0); + + done(); + }); + }); \ No newline at end of file diff --git a/ReactNativeClient/lib/fs-driver-node.js b/ReactNativeClient/lib/fs-driver-node.js index e44ae6377..a83351054 100644 --- a/ReactNativeClient/lib/fs-driver-node.js +++ b/ReactNativeClient/lib/fs-driver-node.js @@ -26,7 +26,8 @@ class FsDriverNode extends FsDriverBase { async writeBinaryFile(path, content) { try { - let buffer = new Buffer(content); + // let buffer = new Buffer(content); + let buffer = Buffer.from(content); return await fs.writeFile(path, buffer); } catch (error) { throw this.fsErrorToJsError_(error, path); @@ -173,7 +174,8 @@ class FsDriverNode extends FsDriverBase { } async readFileChunk(handle, length, encoding = 'base64') { - let buffer = new Buffer(length); + //let buffer = new Buffer(length); + let buffer = Buffer.alloc(length); const result = await fs.read(handle, buffer, 0, length, null); if (!result.bytesRead) return null; buffer = buffer.slice(0, result.bytesRead); diff --git a/ReactNativeClient/lib/models/Note.js b/ReactNativeClient/lib/models/Note.js index 5cdc7a7c2..49ebbe4a2 100644 --- a/ReactNativeClient/lib/models/Note.js +++ b/ReactNativeClient/lib/models/Note.js @@ -207,8 +207,9 @@ class Note extends BaseItem { return ['id', 'title', 'body', 'is_todo', 'todo_completed', 'parent_id', 'updated_time', 'user_updated_time', 'user_created_time', 'encryption_applied']; } - static previewFieldsSql() { - return this.db().escapeFields(this.previewFields()).join(','); + static previewFieldsSql(fields = null) { + if (fields === null) fields = this.previewFields(); + return this.db().escapeFields(fields).join(','); } static async loadFolderNoteByField(folderId, field, value) { @@ -309,8 +310,9 @@ class Note extends BaseItem { return this.search(options); } - static preview(noteId) { - return this.modelSelectOne('SELECT ' + this.previewFieldsSql() + ' FROM notes WHERE is_conflict = 0 AND id = ?', [noteId]); + static preview(noteId, options = null) { + if (!options) options = { fields: null }; + return this.modelSelectOne('SELECT ' + this.previewFieldsSql(options.fields) + ' FROM notes WHERE is_conflict = 0 AND id = ?', [noteId]); } static conflictedNotes() { diff --git a/ReactNativeClient/lib/services/rest/Api.js b/ReactNativeClient/lib/services/rest/Api.js index 4a34a0634..a1a17d5fc 100644 --- a/ReactNativeClient/lib/services/rest/Api.js +++ b/ReactNativeClient/lib/services/rest/Api.js @@ -24,38 +24,56 @@ class ApiError extends Error { } -class MethodNotAllowedError extends ApiError { +class ErrorMethodNotAllowed extends ApiError { - constructor() { - super('Method Not Allowed', 405); + constructor(message = 'Method Not Allowed') { + super(message, 405); } } -class NotFoundError extends ApiError { +class ErrorNotFound extends ApiError { - constructor() { - super('Not Found', 404); + constructor(message = 'Not Found') { + super(message, 404); + } + +} + +class ErrorForbidden extends ApiError { + + constructor(message = 'Forbidden') { + super(message, 404); } } class Api { - constructor() { + constructor(token = null) { + this.token_ = token; this.logger_ = new Logger(); } + get token() { + return this.token_; + } + async route(method, path, query = null, body = null) { path = ltrimSlashes(path); - const callName = 'action_' + path; - if (!this[callName]) throw new NotFoundError(); + if (!path) throw new ErrorNotFound(); // Nothing at the root yet + + const pathParts = path.split('/'); + const callSuffix = pathParts.splice(0,1)[0]; + const callName = 'action_' + callSuffix; + if (!this[callName]) throw new ErrorNotFound(); try { return this[callName]({ method: method, query: query ? query : {}, body: body, + params: pathParts, }); } catch (error) { if (!error.httpCode) error.httpCode = 500; @@ -78,11 +96,17 @@ class Api { return fields.length ? fields : defaultFields; } + checkToken_(request) { + if (!this.token) return; + if (!request.query || !request.query.token) throw new ErrorForbidden('Missing "token" parameter'); + if (request.query.token !== this.token) throw new ErrorForbidden('Invalid "token" parameter'); + } + async action_ping(request) { if (request.method === 'GET') { return 'JoplinClipperServer'; } - throw new MethodNotAllowedError(); + throw new ErrorMethodNotAllowed(); } async action_folders(request) { @@ -90,7 +114,7 @@ class Api { return await Folder.allAsTree({ fields: this.fields_(request, ['id', 'parent_id', 'title']) }); } - throw new MethodNotAllowedError(); + throw new ErrorMethodNotAllowed(); } async action_tags(request) { @@ -98,10 +122,26 @@ class Api { return await Tag.all({ fields: this.fields_(request, ['id', 'title']) }) } - throw new MethodNotAllowedError(); + throw new ErrorMethodNotAllowed(); } async action_notes(request) { + if (request.method === 'GET') { + this.checkToken_(request); + + const noteId = request.params.length ? request.params[0] : null; + const parentId = request.query.parent_id ? request.query.parent_id : null; + const fields = this.fields_(request, []); // previews() already returns default fields + const options = {}; + if (fields.length) options.fields = fields; + + if (noteId) { + return await Note.preview(noteId, options); + } else { + return await Note.previews(parentId, options); + } + } + if (request.method === 'POST') { const requestId = Date.now(); const requestNote = JSON.parse(request.body); @@ -137,7 +177,7 @@ class Api { return note; } - throw new MethodNotAllowedError(); + throw new ErrorMethodNotAllowed(); } diff --git a/ReactNativeClient/lib/shim-init-node.js b/ReactNativeClient/lib/shim-init-node.js index 70eb4aff3..f0dd83a50 100644 --- a/ReactNativeClient/lib/shim-init-node.js +++ b/ReactNativeClient/lib/shim-init-node.js @@ -196,6 +196,7 @@ function shimInit() { const nodeFetch = require('node-fetch'); + // Not used?? shim.readLocalFileBase64 = (path) => { const data = fs.readFileSync(path); return new Buffer(data).toString('base64');