mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
chore: merge master
This commit is contained in:
commit
efdab3e14d
107
CHANGELOG.md
107
CHANGELOG.md
|
@ -1,3 +1,110 @@
|
|||
# [1.1.0](https://github.com/n8n-io/n8n/compare/n8n@1.0.1...n8n@1.1.0) (2023-07-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add missing indices on sqlite ([#6673](https://github.com/n8n-io/n8n/issues/6673)) ([b1838f7](https://github.com/n8n-io/n8n/commit/b1838f7fab3e6d2983fa4d2ba1a480c79f8fe2c5))
|
||||
* **API:** Do not add starting node on workflow creation ([#6686](https://github.com/n8n-io/n8n/issues/6686)) ([92192fb](https://github.com/n8n-io/n8n/commit/92192fbd6108a71fca591e5284269239d4347621))
|
||||
* **API:** Fix issue with workflow setting not supporting newer nanoids ([#6699](https://github.com/n8n-io/n8n/issues/6699)) ([c7e1013](https://github.com/n8n-io/n8n/commit/c7e10130d694347982f50bc0ad1024101e27beea))
|
||||
* **AwsS3 Node:** Fix issue if bucket name contains a '.' ([#6542](https://github.com/n8n-io/n8n/issues/6542)) ([540d32d](https://github.com/n8n-io/n8n/commit/540d32dee4b8927199e047c77acf516d5b824bc3))
|
||||
* **Brevo Node:** Rename SendInBlue node to Brevo node ([#6521](https://github.com/n8n-io/n8n/issues/6521)) ([e63b398](https://github.com/n8n-io/n8n/commit/e63b3982d200ade34461b9159eb1e988f494c025))
|
||||
* **Code Node:** Install python modules always in a user-writable folder ([#6568](https://github.com/n8n-io/n8n/issues/6568)) ([bf35124](https://github.com/n8n-io/n8n/commit/bf351243dfa69095699596e8828904fda025d45c))
|
||||
* **core:** Add empty credential value marker to show empty pw field ([#6532](https://github.com/n8n-io/n8n/issues/6532)) ([9294e2d](https://github.com/n8n-io/n8n/commit/9294e2da3c7c99c2099f5865e610fa7217bf06be))
|
||||
* **core:** Deleting manual executions should defer deleting binary data ([#6680](https://github.com/n8n-io/n8n/issues/6680)) ([462a674](https://github.com/n8n-io/n8n/commit/462a674d1759dc5ae9849daa48cc8c4130dd030e))
|
||||
* **core:** Filter out workflows that failed to activate on startup ([#6676](https://github.com/n8n-io/n8n/issues/6676)) ([667c15d](https://github.com/n8n-io/n8n/commit/667c15d0dfbdab0c29114d5002eed75031c79b42))
|
||||
* **core:** Fix credentials test ([#6569](https://github.com/n8n-io/n8n/issues/6569)) ([1abd172](https://github.com/n8n-io/n8n/commit/1abd172f73e171e37c4cc3ccfaa395c6a46bdf48))
|
||||
* **core:** Fix migrations for MySQL/MariaDB ([#6591](https://github.com/n8n-io/n8n/issues/6591)) ([29882a6](https://github.com/n8n-io/n8n/commit/29882a6f39dddcd1c8c107c20a548ce8dc665cba))
|
||||
* **core:** Handle all uncaught exception, not just the ones from Axios ([#6666](https://github.com/n8n-io/n8n/issues/6666)) ([ff07595](https://github.com/n8n-io/n8n/commit/ff0759530df3780e8eb53a29ec4ab4e98e5755c6))
|
||||
* **core:** Improve the performance of last 2 sqlite migrations ([#6522](https://github.com/n8n-io/n8n/issues/6522)) ([31cba87](https://github.com/n8n-io/n8n/commit/31cba87d307183d613890c7e6d627636b5280b52))
|
||||
* **core:** Load SAML libraries dynamically ([#6690](https://github.com/n8n-io/n8n/issues/6690)) ([fce5609](https://github.com/n8n-io/n8n/commit/fce5609fa32b81ff8e44567233c77a7a1d6232df))
|
||||
* **core:** Redirect user to previous url after SSO signin ([#6710](https://github.com/n8n-io/n8n/issues/6710)) ([08331c6](https://github.com/n8n-io/n8n/commit/08331c63fbc0d69d2203f14165b15e1a596788b0))
|
||||
* **core:** Reduce memory consumption on `BinaryDataManager.init` ([#6633](https://github.com/n8n-io/n8n/issues/6633)) ([329d22f](https://github.com/n8n-io/n8n/commit/329d22f5d1f484d899df885a871f0f32839f0098))
|
||||
* **core:** Remove typeorm patches, but still enforce transactions on every migration ([#6594](https://github.com/n8n-io/n8n/issues/6594)) ([9def7a7](https://github.com/n8n-io/n8n/commit/9def7a729b52cd6b4698c47e190e9e2bd7894da5)), closes [#6519](https://github.com/n8n-io/n8n/issues/6519)
|
||||
* **core:** Rename to credential_stubs and variable_stubs.json ([#6528](https://github.com/n8n-io/n8n/issues/6528)) ([b06462f](https://github.com/n8n-io/n8n/commit/b06462f4415bd1143a00b4a66e6e626da8c52196))
|
||||
* **core:** Support redis cluster in queue mode ([#6708](https://github.com/n8n-io/n8n/issues/6708)) ([4029386](https://github.com/n8n-io/n8n/commit/40293863492d73865f805870937e46f3d0bdaa56))
|
||||
* **core:** Update docker compose setup for V1 images ([#6642](https://github.com/n8n-io/n8n/issues/6642)) ([05007d8](https://github.com/n8n-io/n8n/commit/05007d894e1bfa3550cfd865f85c2844b3db6eea))
|
||||
* **core:** Upgrade semver to address CVE-2022-25883 ([#6689](https://github.com/n8n-io/n8n/issues/6689)) ([9daf944](https://github.com/n8n-io/n8n/commit/9daf944ba53937ddd41bd640a6d473d235f0e16f))
|
||||
* **core:** Use `exec` in docker images to forward signals correctly ([#6732](https://github.com/n8n-io/n8n/issues/6732)) ([ed9f86b](https://github.com/n8n-io/n8n/commit/ed9f86bb95f7080335a336c866cd477669b02002))
|
||||
* **core:** Use JWT as reset password token ([#6714](https://github.com/n8n-io/n8n/issues/6714)) ([89f4402](https://github.com/n8n-io/n8n/commit/89f44021b919181ad58c555a31071c286b866975))
|
||||
* **core:** Use lower cased email for SAML email attribute ([#6663](https://github.com/n8n-io/n8n/issues/6663)) ([eedde24](https://github.com/n8n-io/n8n/commit/eedde24cc046ea517c6d6e455bcdd46a97e4c05b))
|
||||
* **core:** Use owners file to export wf owners ([#6547](https://github.com/n8n-io/n8n/issues/6547)) ([4b755fb](https://github.com/n8n-io/n8n/commit/4b755fb0b441a37eb804c9e70d4b071a341f7155))
|
||||
* **crowd.dev Node:** Fix documentation urls for crowd.dev credentials and nodes ([#6696](https://github.com/n8n-io/n8n/issues/6696)) ([acda7f2](https://github.com/n8n-io/n8n/commit/acda7f269f7b227d430e2308767e1676fda8e165))
|
||||
* **editor:** Add default author name and email to source control settings ([#6543](https://github.com/n8n-io/n8n/issues/6543)) ([e1a02c7](https://github.com/n8n-io/n8n/commit/e1a02c76257de30e08878279dea33d7854d46938))
|
||||
* **editor:** Add paywall state to non owner users for Variables ([#6679](https://github.com/n8n-io/n8n/issues/6679)) ([e7091d6](https://github.com/n8n-io/n8n/commit/e7091d6726eb98a194bc2614c0da332d348180dc))
|
||||
* **editor:** Change default branchColor and remove label ([#6541](https://github.com/n8n-io/n8n/issues/6541)) ([186271e](https://github.com/n8n-io/n8n/commit/186271e939bca19ec9c94d9455e9430d8b8cf9d7))
|
||||
* **editor:** Ensure default credential values are not detected as dirty state ([#6677](https://github.com/n8n-io/n8n/issues/6677)) ([c7b74c3](https://github.com/n8n-io/n8n/commit/c7b74c3c1fdd2f11b8650adf79052681c2f1e248))
|
||||
* **editor:** Extend menu item and use it as a recursive component ([#6618](https://github.com/n8n-io/n8n/issues/6618)) ([d617f63](https://github.com/n8n-io/n8n/commit/d617f63ae9155c03dbf5e597db8e102c1f7a025f))
|
||||
* **editor:** Hide Execute Node button for unknown nodes ([#6684](https://github.com/n8n-io/n8n/issues/6684)) ([6887b4e](https://github.com/n8n-io/n8n/commit/6887b4edeae6536f5b670c55637fde1c5dbd6e40))
|
||||
* **editor:** Increase contrast ratio in execution list workflow names ([#6661](https://github.com/n8n-io/n8n/issues/6661)) ([c0b1cb2](https://github.com/n8n-io/n8n/commit/c0b1cb273e56c04abff5d9893a5e37cda6eb3383))
|
||||
* **editor:** Make Source control branch select required ([#6619](https://github.com/n8n-io/n8n/issues/6619)) ([20737b5](https://github.com/n8n-io/n8n/commit/20737b532423c964bd70e0aa2aac2c9533b5c3d4))
|
||||
* **editor:** Prevent keyboard shortcuts to edit workflows in readonly mode ([#6613](https://github.com/n8n-io/n8n/issues/6613)) ([7383e7f](https://github.com/n8n-io/n8n/commit/7383e7fd48b5c86d43fab4fa47cb1e7a4a4b4043))
|
||||
* **editor:** Prevent RMC from loading schema if it's already cached ([#6695](https://github.com/n8n-io/n8n/issues/6695)) ([a79aa19](https://github.com/n8n-io/n8n/commit/a79aa198330808b7e45b217748fffdabb68098e2))
|
||||
* **editor:** Remove global link styling in v1 banner ([#6705](https://github.com/n8n-io/n8n/issues/6705)) ([76a765a](https://github.com/n8n-io/n8n/commit/76a765a1517f53cb0c4f16a57bdd6f55bc3be0bd))
|
||||
* **editor:** Show appropriate empty workflow list content when instance environment is readonly ([#6610](https://github.com/n8n-io/n8n/issues/6610)) ([7515f7d](https://github.com/n8n-io/n8n/commit/7515f7d52ae72fa1361687c43a9c29f585b3c6ce))
|
||||
* **editor:** Show retry information in execution list only when it exists ([#6587](https://github.com/n8n-io/n8n/issues/6587)) ([3ca66be](https://github.com/n8n-io/n8n/commit/3ca66be38082e7a3866d53d07328be58e913067f))
|
||||
* **editor:** Skip error line highlighting if out of range ([#6721](https://github.com/n8n-io/n8n/issues/6721)) ([a62d00a](https://github.com/n8n-io/n8n/commit/a62d00a4795d02a5905c5ddbae569f122a46a023))
|
||||
* **editor:** Update design system menu item component ([#6659](https://github.com/n8n-io/n8n/issues/6659)) ([84466e9](https://github.com/n8n-io/n8n/commit/84466e983336a3cfa8c20b30ead8d58abbf07cf0))
|
||||
* **FileMaker Node:** Improve returned error responses ([#6585](https://github.com/n8n-io/n8n/issues/6585)) ([91a052e](https://github.com/n8n-io/n8n/commit/91a052e4c53b6717d3a4e4d1034339012ce39c41))
|
||||
* **FTP Node:** List recursive ignore . and .. to prevent infinite loops ([#6707](https://github.com/n8n-io/n8n/issues/6707)) ([995d5cc](https://github.com/n8n-io/n8n/commit/995d5cc47095e584c2a064dd5aa3841b3054ffd4))
|
||||
* **GitLab Trigger Node:** Fix trigger activation 404 error ([#6711](https://github.com/n8n-io/n8n/issues/6711)) ([8ceb832](https://github.com/n8n-io/n8n/commit/8ceb8322ebfc1384291e8a0d5d07ee5c22d52142))
|
||||
* **Gmail Trigger Node:** Early returns in case of no data ([#6727](https://github.com/n8n-io/n8n/issues/6727)) ([c2511a8](https://github.com/n8n-io/n8n/commit/c2511a829cfa40d4d9d570ad7724845c93544c3b))
|
||||
* **Google BigQuery Node:** Error description improvement ([#6715](https://github.com/n8n-io/n8n/issues/6715)) ([95837d2](https://github.com/n8n-io/n8n/commit/95837d260466e8a4bd19c44390ce4557fa5c51cb))
|
||||
* **Google Drive Node:** Fix regex in file RLC ([#6607](https://github.com/n8n-io/n8n/issues/6607)) ([5672146](https://github.com/n8n-io/n8n/commit/56721468dff51bb60ececc0472e2b9ca0740fcb1))
|
||||
* **Google Drive Node:** URL parsing ([#6527](https://github.com/n8n-io/n8n/issues/6527)) ([d9ed0b3](https://github.com/n8n-io/n8n/commit/d9ed0b31b538320a67ee4e5c0cae34656c9f4334))
|
||||
* **Google Sheets Node:** Incorrect read of 0 and false ([#6525](https://github.com/n8n-io/n8n/issues/6525)) ([806d134](https://github.com/n8n-io/n8n/commit/806d13460240abe94843e569b1820cd8d0d8edd1))
|
||||
* **HTTP Request Node:** Cleanup circular references in response ([#6590](https://github.com/n8n-io/n8n/issues/6590)) ([aecc05b](https://github.com/n8n-io/n8n/commit/aecc05b787d09ba778adc5b4bf96abacc5a64204))
|
||||
* **Merge Node:** Enrich input 2 fix ([#6526](https://github.com/n8n-io/n8n/issues/6526)) ([c82c7f1](https://github.com/n8n-io/n8n/commit/c82c7f19128df3a11d6d0f18e8d8dab57e6a3b8f))
|
||||
* **Microsoft Outlook Node:** Fix issue with category not correctly applying ([#6583](https://github.com/n8n-io/n8n/issues/6583)) ([fc8ed55](https://github.com/n8n-io/n8n/commit/fc8ed55c0de7db4cf17f4f1bf417f6cbf48444c2))
|
||||
* **Notion Node:** Version fix ([#6531](https://github.com/n8n-io/n8n/issues/6531)) ([38dc784](https://github.com/n8n-io/n8n/commit/38dc784d2eed25aae777c5c3c3fda1a35e20bd24))
|
||||
* **Postgres Node:** Arrays in query replacement fix ([#6718](https://github.com/n8n-io/n8n/issues/6718)) ([4cae091](https://github.com/n8n-io/n8n/commit/4cae091cfb54701dfa51b5204799df0a8b4929cd))
|
||||
* **Postgres Node:** For select queries, empty result should be be replaced with `{"success":true}` ([#6703](https://github.com/n8n-io/n8n/issues/6703)) ([250175d](https://github.com/n8n-io/n8n/commit/250175d066d6759f4a787371b47ed91ee62aab71))
|
||||
* **Postgres Node:** Upsert does not fetch columns when schema other then public ([#6643](https://github.com/n8n-io/n8n/issues/6643)) ([aaa9ee3](https://github.com/n8n-io/n8n/commit/aaa9ee3949529a745e3b624716da1549ed571604))
|
||||
* **Salesforce Node:** Fix typo for adding a contact to a campaign ([#6598](https://github.com/n8n-io/n8n/issues/6598)) ([7ffe3cb](https://github.com/n8n-io/n8n/commit/7ffe3cb36adeecaca6cc6ddf067a701ee55c18d1))
|
||||
* **Sendy Node:** Fix issue with brand id not being sent ([#6530](https://github.com/n8n-io/n8n/issues/6530)) ([2e8dfb8](https://github.com/n8n-io/n8n/commit/2e8dfb86d4636781b319d6190e8be12e7661ee16))
|
||||
* Stop n8n from complaining about credentials when saving a new workflow form a template ([#6671](https://github.com/n8n-io/n8n/issues/6671)) ([486d16b](https://github.com/n8n-io/n8n/commit/486d16bcdb6be12dd85f4af5f7de878d9d178fd6))
|
||||
* **Strapi Node:** Fix issue with pagination ([#4991](https://github.com/n8n-io/n8n/issues/4991)) ([54444fa](https://github.com/n8n-io/n8n/commit/54444fa388da12d75553e66e53a8cf6f8a99b6fc))
|
||||
* **Telegram Trigger Node:** Add guard to 'include' call on null or undefined ([#6730](https://github.com/n8n-io/n8n/issues/6730)) ([533b0ba](https://github.com/n8n-io/n8n/commit/533b0bac13d275753fee329bb4abe0c7aae5b48b))
|
||||
* **XML Node:** Fix issue with not returning valid data ([#6565](https://github.com/n8n-io/n8n/issues/6565)) ([cdd215f](https://github.com/n8n-io/n8n/commit/cdd215f642b47413c05f229e641074d0d4048f68))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add crowd.dev node and trigger node ([#6082](https://github.com/n8n-io/n8n/issues/6082)) ([238a78f](https://github.com/n8n-io/n8n/commit/238a78f0582dbf439a9799de0edcb2e9bef29978))
|
||||
* Add missing input panels to some trigger nodes ([#6518](https://github.com/n8n-io/n8n/issues/6518)) ([fdf8a42](https://github.com/n8n-io/n8n/commit/fdf8a428ed38bb3ceb2bc0e50b002b34843d8fc4))
|
||||
* Add various source control improvements ([#6533](https://github.com/n8n-io/n8n/issues/6533)) ([68fdc20](https://github.com/n8n-io/n8n/commit/68fdc2078928be478a286774f2889feba1c3f5fe))
|
||||
* **Airtable Node:** Overhaul ([#6200](https://github.com/n8n-io/n8n/issues/6200)) ([b69d20c](https://github.com/n8n-io/n8n/commit/b69d20c12ec1ad0395e23747ce5f1d437de0231b))
|
||||
* Allow `eslint-config` to be externally consumable ([#6694](https://github.com/n8n-io/n8n/issues/6694)) ([3566c13](https://github.com/n8n-io/n8n/commit/3566c13afc9795206b5a4af7b06159e35b046e12))
|
||||
* Allow hiding credential params on cloud ([#6687](https://github.com/n8n-io/n8n/issues/6687)) ([2af1c24](https://github.com/n8n-io/n8n/commit/2af1c24ead4c02e0588d4c2dfcf4a289f54388d4))
|
||||
* **API:** Implement users account quota guards ([#6434](https://github.com/n8n-io/n8n/issues/6434)) ([e5620ab](https://github.com/n8n-io/n8n/commit/e5620ab1e49548e4c2ffd296e055f1caee94d2ba)), closes [#6636](https://github.com/n8n-io/n8n/issues/6636)
|
||||
* **core:** Add cache service ([#6729](https://github.com/n8n-io/n8n/issues/6729)) ([c0d2bac](https://github.com/n8n-io/n8n/commit/c0d2bac94d732d4166633adf9c3b8eaf5d8046be))
|
||||
* **core:** Only show V1 banner to users who migrated ([#6622](https://github.com/n8n-io/n8n/issues/6622)) ([071e56f](https://github.com/n8n-io/n8n/commit/071e56f7fde2fc4ffc7e3da92a069d8ed593bc60))
|
||||
* **editor:** Implement new banners framework ([#6603](https://github.com/n8n-io/n8n/issues/6603)) ([4240e76](https://github.com/n8n-io/n8n/commit/4240e76253e02da13942d4b84a83ec22fd30aca3))
|
||||
* **editor:** Load fixed template list as experiment ([#6632](https://github.com/n8n-io/n8n/issues/6632)) ([e996622](https://github.com/n8n-io/n8n/commit/e9966224ea555ce8f3a48872887a73ef879e47c3))
|
||||
* **editor:** Prevent saving of workflow when canvas is loading ([#6497](https://github.com/n8n-io/n8n/issues/6497)) ([f89ef83](https://github.com/n8n-io/n8n/commit/f89ef83c766fafb1d0497ed91a74b93e8d2af1ec))
|
||||
* **editor:** Removing `ph-no-capture` class from some elements ([#6674](https://github.com/n8n-io/n8n/issues/6674)) ([c3455a4](https://github.com/n8n-io/n8n/commit/c3455a4ad82d965c41267fea173feaad4800c43f))
|
||||
* Environments release using source control ([#6653](https://github.com/n8n-io/n8n/issues/6653)) ([fc7aa8b](https://github.com/n8n-io/n8n/commit/fc7aa8bd664553c463536b6abe58a488e5e11147))
|
||||
* **Google Cloud Storage Node:** Use streaming for file uploads ([#6462](https://github.com/n8n-io/n8n/issues/6462)) ([cd0e41a](https://github.com/n8n-io/n8n/commit/cd0e41a6b49a58bee95721363dd7e6c43de28725))
|
||||
* **Google Drive Node:** Overhaul ([#5941](https://github.com/n8n-io/n8n/issues/5941)) ([d70a1cb](https://github.com/n8n-io/n8n/commit/d70a1cb0c82ee0a4b92776684c6c9079020d028f))
|
||||
* **HTML Node:** 'Convert to table operation ([#6540](https://github.com/n8n-io/n8n/issues/6540)) ([8abb03d](https://github.com/n8n-io/n8n/commit/8abb03d7cf02ad7f03a0adffa646870df5f1a02c))
|
||||
* **HTTP Request Node:** New http request generic custom auth credential ([#5798](https://github.com/n8n-io/n8n/issues/5798)) ([b17b458](https://github.com/n8n-io/n8n/commit/b17b4582a059104665888a2369c3e2256db4c1ed))
|
||||
* **Matrix Node:** Allow setting filename if the binary data has none ([#6536](https://github.com/n8n-io/n8n/issues/6536)) ([8b76e98](https://github.com/n8n-io/n8n/commit/8b76e980852062b192a95593035697c43d6f808e))
|
||||
* **Microsoft To Do Node:** Add an option to set a reminder when creating a task ([#5757](https://github.com/n8n-io/n8n/issues/5757)) ([b19833d](https://github.com/n8n-io/n8n/commit/b19833d673bd554ba86c0b234e8d13633912563a))
|
||||
* **Notion Node:** Add option to update icon when updating a page ([#5670](https://github.com/n8n-io/n8n/issues/5670)) ([225e849](https://github.com/n8n-io/n8n/commit/225e849960ce65d7f85b482f05fb3d7ffb4f9427))
|
||||
* **OpenAI Node:** Update max token limit to support newer model limits ([#6644](https://github.com/n8n-io/n8n/issues/6644)) ([26046f6](https://github.com/n8n-io/n8n/commit/26046f6fe8df9e6fe799f6253d086142f6ce7e53))
|
||||
* **Read PDF Node:** Replace pdf-parse with pdfjs, and add support for streaming and encrypted PDFs ([#6640](https://github.com/n8n-io/n8n/issues/6640)) ([0a31b8e](https://github.com/n8n-io/n8n/commit/0a31b8e2b4aab8d74d80f76598900109fe19a0e8))
|
||||
* **Rundeck Node:** Add support for node filters ([#5633](https://github.com/n8n-io/n8n/issues/5633)) ([1f70f49](https://github.com/n8n-io/n8n/commit/1f70f49ce5784baba7fd779b23209bae4f6b039a))
|
||||
* **Slack Node:** Add option to include link to workflow in Slack node ([#6611](https://github.com/n8n-io/n8n/issues/6611)) ([aa53c46](https://github.com/n8n-io/n8n/commit/aa53c46367480e31642e807ad1abf149fd13eb28))
|
||||
* **Strava Node:** Add hide_from_home field in Activity Update ([#5883](https://github.com/n8n-io/n8n/issues/5883)) ([7495e31](https://github.com/n8n-io/n8n/commit/7495e31a5b25e97683c7ea38225ba253d8fae8b7))
|
||||
* **Telegram Node:** Add support for sending messages to forum topics ([#5746](https://github.com/n8n-io/n8n/issues/5746)) ([e6a81f0](https://github.com/n8n-io/n8n/commit/e6a81f0008fddfcfd5f1102c8e6e58650020d930))
|
||||
* **Twitter Node:** Node overhaul ([#4788](https://github.com/n8n-io/n8n/issues/4788)) ([42721db](https://github.com/n8n-io/n8n/commit/42721dba80077fb796086a2bf0ecce256bf3a50f))
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* Revert "test(editor): Add canvas actions E2E tests" (#6736) ([ed09e9c](https://github.com/n8n-io/n8n/commit/ed09e9c695109a715a4c8d47338bbb0b794eb009)), closes [#6736](https://github.com/n8n-io/n8n/issues/6736) [#6723](https://github.com/n8n-io/n8n/issues/6723)
|
||||
|
||||
|
||||
|
||||
## [1.0.1](https://github.com/n8n-io/n8n/compare/n8n@1.0.0...n8n@1.0.1) (2023-07-05)
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"private": true,
|
||||
"homepage": "https://n8n.io",
|
||||
"engines": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@n8n/client-oauth2",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.0",
|
||||
"scripts": {
|
||||
"clean": "rimraf dist .turbo",
|
||||
"dev": "pnpm watch",
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
/* eslint-disable @typescript-eslint/restrict-plus-operands */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import * as qs from 'querystring';
|
||||
import { Agent } from 'https';
|
||||
import axios from 'axios';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
import { getAuthError } from './utils';
|
||||
import type { ClientOAuth2TokenData } from './ClientOAuth2Token';
|
||||
import { ClientOAuth2Token } from './ClientOAuth2Token';
|
||||
|
@ -18,6 +20,7 @@ export interface ClientOAuth2RequestObject {
|
|||
body?: Record<string, any>;
|
||||
query?: qs.ParsedUrlQuery;
|
||||
headers?: Headers;
|
||||
ignoreSSLIssues?: boolean;
|
||||
}
|
||||
|
||||
export interface ClientOAuth2Options {
|
||||
|
@ -32,6 +35,7 @@ export interface ClientOAuth2Options {
|
|||
state?: string;
|
||||
body?: Record<string, any>;
|
||||
query?: qs.ParsedUrlQuery;
|
||||
ignoreSSLIssues?: boolean;
|
||||
}
|
||||
|
||||
class ResponseError extends Error {
|
||||
|
@ -40,6 +44,8 @@ class ResponseError extends Error {
|
|||
}
|
||||
}
|
||||
|
||||
const sslIgnoringAgent = new Agent({ rejectUnauthorized: false });
|
||||
|
||||
/**
|
||||
* Construct an object that can handle the multiple OAuth 2.0 flows.
|
||||
*/
|
||||
|
@ -86,7 +92,7 @@ export class ClientOAuth2 {
|
|||
url += (url.indexOf('?') === -1 ? '?' : '&') + query;
|
||||
}
|
||||
|
||||
const response = await axios.request({
|
||||
const requestConfig: AxiosRequestConfig = {
|
||||
url,
|
||||
method: options.method,
|
||||
data: qs.stringify(options.body),
|
||||
|
@ -95,7 +101,13 @@ export class ClientOAuth2 {
|
|||
// Axios rejects the promise by default for all status codes 4xx.
|
||||
// We override this to reject promises only on 5xxs
|
||||
validateStatus: (status) => status < 500,
|
||||
});
|
||||
};
|
||||
|
||||
if (options.ignoreSSLIssues) {
|
||||
requestConfig.httpsAgent = sslIgnoringAgent;
|
||||
}
|
||||
|
||||
const response = await axios.request(requestConfig);
|
||||
|
||||
const body = this.parseResponseBody<T>(response.data);
|
||||
|
||||
|
|
|
@ -53,13 +53,13 @@ export class CodeFlow {
|
|||
* the user access token.
|
||||
*/
|
||||
async getToken(
|
||||
uri: string | URL,
|
||||
urlString: string,
|
||||
opts?: Partial<ClientOAuth2Options>,
|
||||
): Promise<ClientOAuth2Token> {
|
||||
const options = { ...this.client.options, ...opts };
|
||||
const options: ClientOAuth2Options = { ...this.client.options, ...opts };
|
||||
expects(options, 'clientId', 'accessTokenUri');
|
||||
|
||||
const url = uri instanceof URL ? uri : new URL(uri, DEFAULT_URL_BASE);
|
||||
const url = new URL(urlString, DEFAULT_URL_BASE);
|
||||
if (
|
||||
typeof options.redirectUri === 'string' &&
|
||||
typeof url.pathname === 'string' &&
|
||||
|
@ -70,7 +70,7 @@ export class CodeFlow {
|
|||
|
||||
if (!url.search?.substring(1)) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
throw new TypeError(`Unable to process uri: ${uri.toString()}`);
|
||||
throw new TypeError(`Unable to process uri: ${urlString}`);
|
||||
}
|
||||
|
||||
const data =
|
||||
|
|
|
@ -63,14 +63,15 @@ export function auth(username: string, password: string): string {
|
|||
*/
|
||||
export function getRequestOptions(
|
||||
{ url, method, body, query, headers }: ClientOAuth2RequestObject,
|
||||
options: any,
|
||||
options: ClientOAuth2Options,
|
||||
): ClientOAuth2RequestObject {
|
||||
const rOptions = {
|
||||
url,
|
||||
method,
|
||||
body: { ...body, ...options.body },
|
||||
query: { ...query, ...options.query },
|
||||
headers: { ...headers, ...options.headers },
|
||||
headers: headers ?? {},
|
||||
ignoreSSLIssues: options.ignoreSSLIssues,
|
||||
};
|
||||
// if request authorization was overridden delete it from header
|
||||
if (rOptions.headers.Authorization === '') {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"description": "n8n Workflow Automation Tool",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
|
@ -41,7 +41,6 @@ import {
|
|||
TagRepository,
|
||||
UserRepository,
|
||||
VariablesRepository,
|
||||
WebhookRepository,
|
||||
WorkflowRepository,
|
||||
WorkflowStatisticsRepository,
|
||||
WorkflowTagMappingRepository,
|
||||
|
@ -187,7 +186,6 @@ export async function init(testConnectionOptions?: ConnectionOptions): Promise<v
|
|||
collections.Tag = Container.get(TagRepository);
|
||||
collections.User = Container.get(UserRepository);
|
||||
collections.Variables = Container.get(VariablesRepository);
|
||||
collections.Webhook = Container.get(WebhookRepository);
|
||||
collections.Workflow = Container.get(WorkflowRepository);
|
||||
collections.WorkflowStatistics = Container.get(WorkflowStatisticsRepository);
|
||||
collections.WorkflowTagMapping = Container.get(WorkflowTagMappingRepository);
|
||||
|
|
|
@ -56,7 +56,6 @@ import type {
|
|||
TagRepository,
|
||||
UserRepository,
|
||||
VariablesRepository,
|
||||
WebhookRepository,
|
||||
WorkflowRepository,
|
||||
WorkflowStatisticsRepository,
|
||||
WorkflowTagMappingRepository,
|
||||
|
@ -103,7 +102,6 @@ export interface IDatabaseCollections extends Record<string, Repository<any>> {
|
|||
Tag: TagRepository;
|
||||
User: UserRepository;
|
||||
Variables: VariablesRepository;
|
||||
Webhook: WebhookRepository;
|
||||
Workflow: WorkflowRepository;
|
||||
WorkflowStatistics: WorkflowStatisticsRepository;
|
||||
WorkflowTagMapping: WorkflowTagMappingRepository;
|
||||
|
|
|
@ -11,7 +11,6 @@ const defaultUserProps = {
|
|||
lastName: null,
|
||||
email: null,
|
||||
password: null,
|
||||
resetPasswordToken: null,
|
||||
};
|
||||
|
||||
export class Reset extends BaseCommand {
|
||||
|
|
|
@ -265,6 +265,7 @@ oauth2CredentialController.get(
|
|||
redirectUri: `${getInstanceBaseUrl()}/${restEndpoint}/oauth2-credential/callback`,
|
||||
scopes: split(scopes, ','),
|
||||
scopesSeparator: scopes.includes(',') ? ',' : ' ',
|
||||
ignoreSSLIssues: get(oauthCredentials, 'ignoreSSLIssues') as boolean,
|
||||
};
|
||||
|
||||
if (oauthCredentials.grantType === 'pkce') {
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
import { BeforeUpdate, CreateDateColumn, UpdateDateColumn } from 'typeorm';
|
||||
import {
|
||||
BeforeInsert,
|
||||
BeforeUpdate,
|
||||
CreateDateColumn,
|
||||
PrimaryColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { IsDate, IsOptional } from 'class-validator';
|
||||
import config from '@/config';
|
||||
import { generateNanoId } from '../utils/generators';
|
||||
|
||||
const dbType = config.getEnv('database.type');
|
||||
|
||||
|
@ -14,18 +21,37 @@ const timestampSyntax = {
|
|||
export const jsonColumnType = dbType === 'sqlite' ? 'simple-json' : 'json';
|
||||
export const datetimeColumnType = dbType === 'postgresdb' ? 'timestamptz' : 'datetime';
|
||||
|
||||
export abstract class AbstractEntity {
|
||||
@CreateDateColumn({
|
||||
const tsColumnOptions = {
|
||||
precision: 3,
|
||||
default: () => timestampSyntax,
|
||||
})
|
||||
};
|
||||
|
||||
type Constructor<T> = new (...args: any[]) => T;
|
||||
|
||||
function mixinStringId<T extends Constructor<{}>>(base: T) {
|
||||
class Derived extends base {
|
||||
@PrimaryColumn('varchar')
|
||||
id: string;
|
||||
|
||||
@BeforeInsert()
|
||||
generateId() {
|
||||
if (!this.id) {
|
||||
this.id = generateNanoId();
|
||||
}
|
||||
}
|
||||
}
|
||||
return Derived;
|
||||
}
|
||||
|
||||
function mixinTimestamps<T extends Constructor<{}>>(base: T) {
|
||||
class Derived extends base {
|
||||
@CreateDateColumn(tsColumnOptions)
|
||||
@IsOptional() // ignored by validation because set at DB level
|
||||
@IsDate()
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({
|
||||
precision: 3,
|
||||
default: () => timestampSyntax,
|
||||
...tsColumnOptions,
|
||||
onUpdate: timestampSyntax,
|
||||
})
|
||||
@IsOptional() // ignored by validation because set at DB level
|
||||
|
@ -36,4 +62,12 @@ export abstract class AbstractEntity {
|
|||
setUpdateDate(): void {
|
||||
this.updatedAt = new Date();
|
||||
}
|
||||
}
|
||||
return Derived;
|
||||
}
|
||||
|
||||
class BaseEntity {}
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
export const WithStringId = mixinStringId(BaseEntity);
|
||||
export const WithTimestamps = mixinTimestamps(BaseEntity);
|
||||
export const WithTimestampsAndStringId = mixinStringId(WithTimestamps);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { Column, Entity, ManyToOne, PrimaryColumn, Unique } from 'typeorm';
|
||||
import { AbstractEntity } from './AbstractEntity';
|
||||
import { WithTimestamps } from './AbstractEntity';
|
||||
import { User } from './User';
|
||||
|
||||
export type AuthProviderType = 'ldap' | 'email' | 'saml'; // | 'google';
|
||||
|
||||
@Entity()
|
||||
@Unique(['providerId', 'providerType'])
|
||||
export class AuthIdentity extends AbstractEntity {
|
||||
export class AuthIdentity extends WithTimestamps {
|
||||
@Column()
|
||||
userId: string;
|
||||
|
||||
|
|
|
@ -1,30 +1,12 @@
|
|||
import type { ICredentialNodeAccess } from 'n8n-workflow';
|
||||
import { BeforeInsert, Column, Entity, Index, OneToMany, PrimaryColumn } from 'typeorm';
|
||||
import { Column, Entity, Index, OneToMany } from 'typeorm';
|
||||
import { IsArray, IsObject, IsString, Length } from 'class-validator';
|
||||
import type { SharedCredentials } from './SharedCredentials';
|
||||
import { AbstractEntity, jsonColumnType } from './AbstractEntity';
|
||||
import { WithTimestampsAndStringId, jsonColumnType } from './AbstractEntity';
|
||||
import type { ICredentialsDb } from '@/Interfaces';
|
||||
import { generateNanoId } from '../utils/generators';
|
||||
|
||||
@Entity()
|
||||
export class CredentialsEntity extends AbstractEntity implements ICredentialsDb {
|
||||
constructor(data?: Partial<CredentialsEntity>) {
|
||||
super();
|
||||
Object.assign(this, data);
|
||||
if (!this.id) {
|
||||
this.id = generateNanoId();
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeInsert()
|
||||
nanoId(): void {
|
||||
if (!this.id) {
|
||||
this.id = generateNanoId();
|
||||
}
|
||||
}
|
||||
|
||||
@PrimaryColumn('varchar')
|
||||
id: string;
|
||||
|
||||
export class CredentialsEntity extends WithTimestampsAndStringId implements ICredentialsDb {
|
||||
@Column({ length: 128 })
|
||||
@IsString({ message: 'Credential `name` must be of type string.' })
|
||||
@Length(3, 128, {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { MessageEventBusDestinationOptions } from 'n8n-workflow';
|
||||
import { Column, Entity, PrimaryColumn } from 'typeorm';
|
||||
import { AbstractEntity, jsonColumnType } from './AbstractEntity';
|
||||
import { WithTimestamps, jsonColumnType } from './AbstractEntity';
|
||||
|
||||
@Entity({ name: 'event_destinations' })
|
||||
export class EventDestinations extends AbstractEntity {
|
||||
export class EventDestinations extends WithTimestamps {
|
||||
@PrimaryColumn('uuid')
|
||||
id: string;
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { Column, Entity, JoinColumn, OneToMany, PrimaryColumn } from 'typeorm';
|
||||
import type { InstalledNodes } from './InstalledNodes';
|
||||
import { AbstractEntity } from './AbstractEntity';
|
||||
import { WithTimestamps } from './AbstractEntity';
|
||||
|
||||
@Entity()
|
||||
export class InstalledPackages extends AbstractEntity {
|
||||
export class InstalledPackages extends WithTimestamps {
|
||||
@PrimaryColumn()
|
||||
packageName: string;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import { IsString, Length } from 'class-validator';
|
|||
import type { User } from './User';
|
||||
import type { SharedWorkflow } from './SharedWorkflow';
|
||||
import type { SharedCredentials } from './SharedCredentials';
|
||||
import { AbstractEntity } from './AbstractEntity';
|
||||
import { WithTimestamps } from './AbstractEntity';
|
||||
import { idStringifier } from '../utils/transformers';
|
||||
|
||||
export type RoleNames = 'owner' | 'member' | 'user' | 'editor';
|
||||
|
@ -12,7 +12,7 @@ export type RoleScopes = 'global' | 'workflow' | 'credential';
|
|||
|
||||
@Entity()
|
||||
@Unique(['scope', 'name'])
|
||||
export class Role extends AbstractEntity {
|
||||
export class Role extends WithTimestamps {
|
||||
@PrimaryColumn({ transformer: idStringifier })
|
||||
id: string;
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@ import { Column, Entity, ManyToOne, PrimaryColumn } from 'typeorm';
|
|||
import { CredentialsEntity } from './CredentialsEntity';
|
||||
import { User } from './User';
|
||||
import { Role } from './Role';
|
||||
import { AbstractEntity } from './AbstractEntity';
|
||||
import { WithTimestamps } from './AbstractEntity';
|
||||
|
||||
@Entity()
|
||||
export class SharedCredentials extends AbstractEntity {
|
||||
export class SharedCredentials extends WithTimestamps {
|
||||
@ManyToOne('Role', 'sharedCredentials', { nullable: false })
|
||||
role: Role;
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@ import { Column, Entity, ManyToOne, PrimaryColumn } from 'typeorm';
|
|||
import { WorkflowEntity } from './WorkflowEntity';
|
||||
import { User } from './User';
|
||||
import { Role } from './Role';
|
||||
import { AbstractEntity } from './AbstractEntity';
|
||||
import { WithTimestamps } from './AbstractEntity';
|
||||
|
||||
@Entity()
|
||||
export class SharedWorkflow extends AbstractEntity {
|
||||
export class SharedWorkflow extends WithTimestamps {
|
||||
@ManyToOne('Role', 'sharedWorkflows', { nullable: false })
|
||||
role: Role;
|
||||
|
||||
|
|
|
@ -1,30 +1,11 @@
|
|||
import { BeforeInsert, Column, Entity, Index, ManyToMany, OneToMany, PrimaryColumn } from 'typeorm';
|
||||
import { Column, Entity, Index, ManyToMany, OneToMany } from 'typeorm';
|
||||
import { IsString, Length } from 'class-validator';
|
||||
import type { WorkflowEntity } from './WorkflowEntity';
|
||||
import type { WorkflowTagMapping } from './WorkflowTagMapping';
|
||||
import { AbstractEntity } from './AbstractEntity';
|
||||
import { generateNanoId } from '../utils/generators';
|
||||
import { WithTimestampsAndStringId } from './AbstractEntity';
|
||||
|
||||
@Entity()
|
||||
export class TagEntity extends AbstractEntity {
|
||||
constructor(data?: Partial<TagEntity>) {
|
||||
super();
|
||||
Object.assign(this, data);
|
||||
if (!this.id) {
|
||||
this.id = generateNanoId();
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeInsert()
|
||||
nanoId() {
|
||||
if (!this.id) {
|
||||
this.id = generateNanoId();
|
||||
}
|
||||
}
|
||||
|
||||
@PrimaryColumn('varchar')
|
||||
id: string;
|
||||
|
||||
export class TagEntity extends WithTimestampsAndStringId {
|
||||
@Column({ length: 24 })
|
||||
@Index({ unique: true })
|
||||
@IsString({ message: 'Tag name must be of type string.' })
|
||||
|
|
|
@ -17,7 +17,7 @@ import type { SharedWorkflow } from './SharedWorkflow';
|
|||
import type { SharedCredentials } from './SharedCredentials';
|
||||
import { NoXss } from '../utils/customValidators';
|
||||
import { objectRetriever, lowerCaser } from '../utils/transformers';
|
||||
import { AbstractEntity, jsonColumnType } from './AbstractEntity';
|
||||
import { WithTimestamps, jsonColumnType } from './AbstractEntity';
|
||||
import type { IPersonalizationSurveyAnswers } from '@/Interfaces';
|
||||
import type { AuthIdentity } from './AuthIdentity';
|
||||
|
||||
|
@ -26,7 +26,7 @@ export const MIN_PASSWORD_LENGTH = 8;
|
|||
export const MAX_PASSWORD_LENGTH = 64;
|
||||
|
||||
@Entity()
|
||||
export class User extends AbstractEntity implements IUser {
|
||||
export class User extends WithTimestamps implements IUser {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
|
|
|
@ -1,25 +1,8 @@
|
|||
import { BeforeInsert, Column, Entity, PrimaryColumn } from 'typeorm';
|
||||
import { generateNanoId } from '../utils/generators';
|
||||
import { Column, Entity } from 'typeorm';
|
||||
import { WithStringId } from './AbstractEntity';
|
||||
|
||||
@Entity()
|
||||
export class Variables {
|
||||
constructor(data?: Partial<Variables>) {
|
||||
Object.assign(this, data);
|
||||
if (!this.id) {
|
||||
this.id = generateNanoId();
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeInsert()
|
||||
nanoId() {
|
||||
if (!this.id) {
|
||||
this.id = generateNanoId();
|
||||
}
|
||||
}
|
||||
|
||||
@PrimaryColumn('varchar')
|
||||
id: string;
|
||||
|
||||
export class Variables extends WithStringId {
|
||||
@Column('text')
|
||||
key: string;
|
||||
|
||||
|
|
|
@ -3,17 +3,7 @@ import { Length } from 'class-validator';
|
|||
import { IConnections, IDataObject, IWorkflowSettings } from 'n8n-workflow';
|
||||
import type { IBinaryKeyData, INode, IPairedItemData } from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
BeforeInsert,
|
||||
Column,
|
||||
Entity,
|
||||
Index,
|
||||
JoinColumn,
|
||||
JoinTable,
|
||||
ManyToMany,
|
||||
OneToMany,
|
||||
PrimaryColumn,
|
||||
} from 'typeorm';
|
||||
import { Column, Entity, Index, JoinColumn, JoinTable, ManyToMany, OneToMany } from 'typeorm';
|
||||
|
||||
import config from '@/config';
|
||||
import type { TagEntity } from './TagEntity';
|
||||
|
@ -21,30 +11,11 @@ import type { SharedWorkflow } from './SharedWorkflow';
|
|||
import type { WorkflowStatistics } from './WorkflowStatistics';
|
||||
import type { WorkflowTagMapping } from './WorkflowTagMapping';
|
||||
import { objectRetriever, sqlite } from '../utils/transformers';
|
||||
import { AbstractEntity, jsonColumnType } from './AbstractEntity';
|
||||
import { WithTimestampsAndStringId, jsonColumnType } from './AbstractEntity';
|
||||
import type { IWorkflowDb } from '@/Interfaces';
|
||||
import { generateNanoId } from '../utils/generators';
|
||||
|
||||
@Entity()
|
||||
export class WorkflowEntity extends AbstractEntity implements IWorkflowDb {
|
||||
constructor(data?: Partial<WorkflowEntity>) {
|
||||
super();
|
||||
Object.assign(this, data);
|
||||
if (!this.id) {
|
||||
this.id = generateNanoId();
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeInsert()
|
||||
nanoId() {
|
||||
if (!this.id) {
|
||||
this.id = generateNanoId();
|
||||
}
|
||||
}
|
||||
|
||||
@PrimaryColumn('varchar')
|
||||
id: string;
|
||||
|
||||
export class WorkflowEntity extends WithTimestampsAndStringId implements IWorkflowDb {
|
||||
// TODO: Add XSS check
|
||||
@Index({ unique: true })
|
||||
@Length(1, 128, {
|
||||
|
|
|
@ -14,7 +14,7 @@ import { readFile as fsReadFile } from 'fs/promises';
|
|||
import { Credentials, UserSettings } from 'n8n-core';
|
||||
import type { IWorkflowToImport } from '@/Interfaces';
|
||||
import type { ExportableCredential } from './types/exportableCredential';
|
||||
import { Variables } from '@db/entities/Variables';
|
||||
import type { Variables } from '@db/entities/Variables';
|
||||
import { UM_FIX_INSTRUCTION } from '@/commands/BaseCommand';
|
||||
import { SharedCredentials } from '@db/entities/SharedCredentials';
|
||||
import type { WorkflowTagMapping } from '@db/entities/WorkflowTagMapping';
|
||||
|
@ -576,7 +576,7 @@ export class SourceControlImportService {
|
|||
if (overriddenKeys.length > 0 && valueOverrides) {
|
||||
for (const key of overriddenKeys) {
|
||||
result.imported.push(key);
|
||||
const newVariable = new Variables({ key, value: valueOverrides[key] });
|
||||
const newVariable = Db.collections.Variables.create({ key, value: valueOverrides[key] });
|
||||
await Db.collections.Variables.save(newVariable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import { audit } from '@/audit';
|
|||
import { FILESYSTEM_INTERACTION_NODE_TYPES, FILESYSTEM_REPORT } from '@/audit/constants';
|
||||
import { getRiskSection, saveManualTriggerWorkflow } from './utils';
|
||||
import * as testDb from '../shared/testDb';
|
||||
import { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
||||
|
||||
beforeAll(async () => {
|
||||
await testDb.init();
|
||||
|
@ -27,7 +26,7 @@ test('should report filesystem interaction nodes', async () => {
|
|||
);
|
||||
|
||||
const promises = Object.entries(map).map(async ([nodeType, nodeId]) => {
|
||||
const details = new WorkflowEntity({
|
||||
const details = Db.collections.Workflow.create({
|
||||
name: 'My Test Workflow',
|
||||
active: false,
|
||||
connections: {},
|
||||
|
|
|
@ -9,7 +9,6 @@ import { toReportTitle } from '@/audit/utils';
|
|||
import { mockInstance } from '../shared/utils/';
|
||||
import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials';
|
||||
import { NodeTypes } from '@/NodeTypes';
|
||||
import { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
||||
|
||||
const nodesAndCredentials = mockInstance(LoadNodesAndCredentials);
|
||||
nodesAndCredentials.getCustomDirectories.mockReturnValue([]);
|
||||
|
@ -33,7 +32,7 @@ test('should report risky official nodes', async () => {
|
|||
}, {});
|
||||
|
||||
const promises = Object.entries(map).map(async ([nodeType, nodeId]) => {
|
||||
const details = new WorkflowEntity({
|
||||
const details = Db.collections.Workflow.create({
|
||||
name: 'My Test Workflow',
|
||||
active: false,
|
||||
connections: {},
|
||||
|
|
|
@ -47,17 +47,8 @@ describe('POST /login', () => {
|
|||
|
||||
expect(response.statusCode).toBe(200);
|
||||
|
||||
const {
|
||||
id,
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
password,
|
||||
personalizationAnswers,
|
||||
globalRole,
|
||||
resetPasswordToken,
|
||||
apiKey,
|
||||
} = response.body.data;
|
||||
const { id, email, firstName, lastName, password, personalizationAnswers, globalRole, apiKey } =
|
||||
response.body.data;
|
||||
|
||||
expect(validator.isUUID(id)).toBe(true);
|
||||
expect(email).toBe(owner.email);
|
||||
|
@ -66,7 +57,6 @@ describe('POST /login', () => {
|
|||
expect(password).toBeUndefined();
|
||||
expect(personalizationAnswers).toBeNull();
|
||||
expect(password).toBeUndefined();
|
||||
expect(resetPasswordToken).toBeUndefined();
|
||||
expect(globalRole).toBeDefined();
|
||||
expect(globalRole.name).toBe('owner');
|
||||
expect(globalRole.scope).toBe('global');
|
||||
|
@ -137,17 +127,8 @@ describe('GET /login', () => {
|
|||
|
||||
expect(response.statusCode).toBe(200);
|
||||
|
||||
const {
|
||||
id,
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
password,
|
||||
personalizationAnswers,
|
||||
globalRole,
|
||||
resetPasswordToken,
|
||||
apiKey,
|
||||
} = response.body.data;
|
||||
const { id, email, firstName, lastName, password, personalizationAnswers, globalRole, apiKey } =
|
||||
response.body.data;
|
||||
|
||||
expect(validator.isUUID(id)).toBe(true);
|
||||
expect(email).toBeDefined();
|
||||
|
@ -156,7 +137,6 @@ describe('GET /login', () => {
|
|||
expect(password).toBeUndefined();
|
||||
expect(personalizationAnswers).toBeNull();
|
||||
expect(password).toBeUndefined();
|
||||
expect(resetPasswordToken).toBeUndefined();
|
||||
expect(globalRole).toBeDefined();
|
||||
expect(globalRole.name).toBe('owner');
|
||||
expect(globalRole.scope).toBe('global');
|
||||
|
@ -173,17 +153,8 @@ describe('GET /login', () => {
|
|||
|
||||
expect(response.statusCode).toBe(200);
|
||||
|
||||
const {
|
||||
id,
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
password,
|
||||
personalizationAnswers,
|
||||
globalRole,
|
||||
resetPasswordToken,
|
||||
apiKey,
|
||||
} = response.body.data;
|
||||
const { id, email, firstName, lastName, password, personalizationAnswers, globalRole, apiKey } =
|
||||
response.body.data;
|
||||
|
||||
expect(validator.isUUID(id)).toBe(true);
|
||||
expect(email).toBeDefined();
|
||||
|
@ -192,7 +163,6 @@ describe('GET /login', () => {
|
|||
expect(password).toBeUndefined();
|
||||
expect(personalizationAnswers).toBeNull();
|
||||
expect(password).toBeUndefined();
|
||||
expect(resetPasswordToken).toBeUndefined();
|
||||
expect(globalRole).toBeDefined();
|
||||
expect(globalRole.name).toBe('member');
|
||||
expect(globalRole.scope).toBe('global');
|
||||
|
@ -209,17 +179,8 @@ describe('GET /login', () => {
|
|||
|
||||
expect(response.statusCode).toBe(200);
|
||||
|
||||
const {
|
||||
id,
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
password,
|
||||
personalizationAnswers,
|
||||
globalRole,
|
||||
resetPasswordToken,
|
||||
apiKey,
|
||||
} = response.body.data;
|
||||
const { id, email, firstName, lastName, password, personalizationAnswers, globalRole, apiKey } =
|
||||
response.body.data;
|
||||
|
||||
expect(validator.isUUID(id)).toBe(true);
|
||||
expect(email).toBe(owner.email);
|
||||
|
@ -228,7 +189,6 @@ describe('GET /login', () => {
|
|||
expect(password).toBeUndefined();
|
||||
expect(personalizationAnswers).toBeNull();
|
||||
expect(password).toBeUndefined();
|
||||
expect(resetPasswordToken).toBeUndefined();
|
||||
expect(globalRole).toBeDefined();
|
||||
expect(globalRole.name).toBe('owner');
|
||||
expect(globalRole.scope).toBe('global');
|
||||
|
@ -245,17 +205,8 @@ describe('GET /login', () => {
|
|||
|
||||
expect(response.statusCode).toBe(200);
|
||||
|
||||
const {
|
||||
id,
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
password,
|
||||
personalizationAnswers,
|
||||
globalRole,
|
||||
resetPasswordToken,
|
||||
apiKey,
|
||||
} = response.body.data;
|
||||
const { id, email, firstName, lastName, password, personalizationAnswers, globalRole, apiKey } =
|
||||
response.body.data;
|
||||
|
||||
expect(validator.isUUID(id)).toBe(true);
|
||||
expect(email).toBe(member.email);
|
||||
|
@ -264,7 +215,6 @@ describe('GET /login', () => {
|
|||
expect(password).toBeUndefined();
|
||||
expect(personalizationAnswers).toBeNull();
|
||||
expect(password).toBeUndefined();
|
||||
expect(resetPasswordToken).toBeUndefined();
|
||||
expect(globalRole).toBeDefined();
|
||||
expect(globalRole.name).toBe('member');
|
||||
expect(globalRole.scope).toBe('global');
|
||||
|
|
|
@ -42,7 +42,5 @@ test.skip('user-management:reset should reset DB to default user state', async (
|
|||
expect(user.firstName).toBeNull();
|
||||
expect(user.lastName).toBeNull();
|
||||
expect(user.password).toBeNull();
|
||||
expect(user.resetPasswordToken).toBeNull();
|
||||
expect(user.resetPasswordTokenExpiration).toBeNull();
|
||||
expect(user.personalizationAnswers).toBeNull();
|
||||
});
|
||||
|
|
|
@ -53,7 +53,6 @@ describe('Owner shell', () => {
|
|||
personalizationAnswers,
|
||||
globalRole,
|
||||
password,
|
||||
resetPasswordToken,
|
||||
isPending,
|
||||
apiKey,
|
||||
} = response.body.data;
|
||||
|
@ -64,7 +63,6 @@ describe('Owner shell', () => {
|
|||
expect(lastName).toBe(validPayload.lastName);
|
||||
expect(personalizationAnswers).toBeNull();
|
||||
expect(password).toBeUndefined();
|
||||
expect(resetPasswordToken).toBeUndefined();
|
||||
expect(isPending).toBe(false);
|
||||
expect(globalRole.name).toBe('owner');
|
||||
expect(globalRole.scope).toBe('global');
|
||||
|
@ -198,7 +196,6 @@ describe('Member', () => {
|
|||
personalizationAnswers,
|
||||
globalRole,
|
||||
password,
|
||||
resetPasswordToken,
|
||||
isPending,
|
||||
apiKey,
|
||||
} = response.body.data;
|
||||
|
@ -209,7 +206,6 @@ describe('Member', () => {
|
|||
expect(lastName).toBe(validPayload.lastName);
|
||||
expect(personalizationAnswers).toBeNull();
|
||||
expect(password).toBeUndefined();
|
||||
expect(resetPasswordToken).toBeUndefined();
|
||||
expect(isPending).toBe(false);
|
||||
expect(globalRole.name).toBe('member');
|
||||
expect(globalRole.scope).toBe('global');
|
||||
|
@ -334,7 +330,6 @@ describe('Owner', () => {
|
|||
personalizationAnswers,
|
||||
globalRole,
|
||||
password,
|
||||
resetPasswordToken,
|
||||
isPending,
|
||||
apiKey,
|
||||
} = response.body.data;
|
||||
|
@ -345,7 +340,6 @@ describe('Owner', () => {
|
|||
expect(lastName).toBe(validPayload.lastName);
|
||||
expect(personalizationAnswers).toBeNull();
|
||||
expect(password).toBeUndefined();
|
||||
expect(resetPasswordToken).toBeUndefined();
|
||||
expect(isPending).toBe(false);
|
||||
expect(globalRole.name).toBe('owner');
|
||||
expect(globalRole.scope).toBe('global');
|
||||
|
|
|
@ -55,7 +55,6 @@ describe('POST /owner/setup', () => {
|
|||
personalizationAnswers,
|
||||
globalRole,
|
||||
password,
|
||||
resetPasswordToken,
|
||||
isPending,
|
||||
apiKey,
|
||||
} = response.body.data;
|
||||
|
@ -67,7 +66,6 @@ describe('POST /owner/setup', () => {
|
|||
expect(personalizationAnswers).toBeNull();
|
||||
expect(password).toBeUndefined();
|
||||
expect(isPending).toBe(false);
|
||||
expect(resetPasswordToken).toBeUndefined();
|
||||
expect(globalRole.name).toBe('owner');
|
||||
expect(globalRole.scope).toBe('global');
|
||||
expect(apiKey).toBeUndefined();
|
||||
|
|
|
@ -73,7 +73,6 @@ describe('With license unlimited quota:users', () => {
|
|||
personalizationAnswers,
|
||||
globalRole,
|
||||
password,
|
||||
resetPasswordToken,
|
||||
isPending,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
|
@ -85,7 +84,6 @@ describe('With license unlimited quota:users', () => {
|
|||
expect(lastName).toBeDefined();
|
||||
expect(personalizationAnswers).toBeUndefined();
|
||||
expect(password).toBeUndefined();
|
||||
expect(resetPasswordToken).toBeUndefined();
|
||||
expect(isPending).toBe(false);
|
||||
expect(globalRole).toBeUndefined();
|
||||
expect(createdAt).toBeDefined();
|
||||
|
@ -144,7 +142,6 @@ describe('With license unlimited quota:users', () => {
|
|||
personalizationAnswers,
|
||||
globalRole,
|
||||
password,
|
||||
resetPasswordToken,
|
||||
isPending,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
|
@ -156,7 +153,6 @@ describe('With license unlimited quota:users', () => {
|
|||
expect(lastName).toBeDefined();
|
||||
expect(personalizationAnswers).toBeUndefined();
|
||||
expect(password).toBeUndefined();
|
||||
expect(resetPasswordToken).toBeUndefined();
|
||||
expect(globalRole).toBeUndefined();
|
||||
expect(createdAt).toBeDefined();
|
||||
expect(isPending).toBeDefined();
|
||||
|
@ -192,7 +188,6 @@ describe('With license unlimited quota:users', () => {
|
|||
personalizationAnswers,
|
||||
globalRole,
|
||||
password,
|
||||
resetPasswordToken,
|
||||
isPending,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
|
@ -204,7 +199,6 @@ describe('With license unlimited quota:users', () => {
|
|||
expect(lastName).toBeDefined();
|
||||
expect(personalizationAnswers).toBeUndefined();
|
||||
expect(password).toBeUndefined();
|
||||
expect(resetPasswordToken).toBeUndefined();
|
||||
expect(isPending).toBe(false);
|
||||
expect(globalRole).toBeUndefined();
|
||||
expect(createdAt).toBeDefined();
|
||||
|
|
|
@ -19,7 +19,7 @@ import { InstalledPackages } from '@db/entities/InstalledPackages';
|
|||
import type { Role } from '@db/entities/Role';
|
||||
import type { TagEntity } from '@db/entities/TagEntity';
|
||||
import type { User } from '@db/entities/User';
|
||||
import { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
||||
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
||||
import { RoleRepository } from '@db/repositories';
|
||||
import type { ICredentialsDb } from '@/Interfaces';
|
||||
|
||||
|
@ -412,7 +412,7 @@ export async function createManyWorkflows(
|
|||
export async function createWorkflow(attributes: Partial<WorkflowEntity> = {}, user?: User) {
|
||||
const { active, name, nodes, connections } = attributes;
|
||||
|
||||
const workflowEntity = new WorkflowEntity({
|
||||
const workflowEntity = Db.collections.Workflow.create({
|
||||
active: active ?? false,
|
||||
name: name ?? 'test workflow',
|
||||
nodes: nodes ?? [
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-core",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"description": "Core functionality of n8n",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
|
@ -1092,6 +1092,7 @@ export async function requestOAuth2(
|
|||
clientSecret: credentials.clientSecret as string,
|
||||
accessTokenUri: credentials.accessTokenUrl as string,
|
||||
scopes: (credentials.scope as string).split(' '),
|
||||
ignoreSSLIssues: credentials.ignoreSSLIssues as boolean,
|
||||
});
|
||||
|
||||
let oauthTokenData = credentials.oauthTokenData as ClientOAuth2TokenData;
|
||||
|
@ -1131,6 +1132,9 @@ export async function requestOAuth2(
|
|||
},
|
||||
oAuth2Options?.tokenType || oauthTokenData.tokenType,
|
||||
);
|
||||
|
||||
(requestOptions as OptionsWithUri).rejectUnauthorized = !credentials.ignoreSSLIssues;
|
||||
|
||||
// Signs the request by adding authorization headers or query parameters depending
|
||||
// on the token-type used.
|
||||
const newRequestOptions = token.sign(requestOptions as ClientOAuth2RequestObject);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-design-system",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
"author": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-editor-ui",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"description": "Workflow Editor UI for n8n",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
|
@ -33,11 +33,6 @@ const tooltipOpenDelay = ref(300);
|
|||
const currentBranch = computed(() => {
|
||||
return sourceControlStore.preferences.branchName;
|
||||
});
|
||||
const featureEnabled = computed(() => window.localStorage.getItem('source-control'));
|
||||
// TODO: use this for release
|
||||
// const featureEnabled = computed(
|
||||
// () => sourceControlStore.preferences.connected && sourceControlStore.preferences.branchName,
|
||||
// );
|
||||
const isInstanceOwner = computed(() => usersStore.isInstanceOwner);
|
||||
const setupButtonTooltipPlacement = computed(() => (props.isCollapsed ? 'right' : 'top'));
|
||||
|
||||
|
@ -127,11 +122,11 @@ const goToSourceControlSetup = async () => {
|
|||
|
||||
<template>
|
||||
<div
|
||||
v-if="featureEnabled && isInstanceOwner"
|
||||
v-if="sourceControlStore.isEnterpriseSourceControlEnabled && isInstanceOwner"
|
||||
:class="{
|
||||
[$style.sync]: true,
|
||||
[$style.collapsed]: isCollapsed,
|
||||
[$style.isConnected]: featureEnabled,
|
||||
[$style.isConnected]: sourceControlStore.isEnterpriseSourceControlEnabled,
|
||||
}"
|
||||
:style="{ borderLeftColor: sourceControlStore.preferences.branchColor }"
|
||||
data-test-id="main-sidebar-source-control"
|
||||
|
|
|
@ -19,10 +19,7 @@ let usersStore: ReturnType<typeof useUsersStore>;
|
|||
const renderComponent = createComponentRenderer(MainSidebarSourceControl);
|
||||
|
||||
describe('MainSidebarSourceControl', () => {
|
||||
const getItemSpy = vi.spyOn(Storage.prototype, 'getItem');
|
||||
|
||||
beforeEach(() => {
|
||||
getItemSpy.mockReturnValue('true');
|
||||
pinia = createTestingPinia({
|
||||
initialState: {
|
||||
[STORES.SETTINGS]: {
|
||||
|
@ -32,31 +29,22 @@ describe('MainSidebarSourceControl', () => {
|
|||
});
|
||||
|
||||
usersStore = useUsersStore(pinia);
|
||||
|
||||
vi.spyOn(usersStore, 'isInstanceOwner', 'get').mockReturnValue(true);
|
||||
|
||||
sourceControlStore = useSourceControlStore();
|
||||
vi.spyOn(sourceControlStore, 'isEnterpriseSourceControlEnabled', 'get').mockReturnValue(true);
|
||||
|
||||
uiStore = useUIStore();
|
||||
});
|
||||
|
||||
it('should render nothing', async () => {
|
||||
getItemSpy.mockReturnValue(null);
|
||||
const { container } = renderComponent({
|
||||
props: { isCollapsed: false },
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
it('should render nothing when not instance owner', async () => {
|
||||
vi.spyOn(usersStore, 'isInstanceOwner', 'get').mockReturnValue(false);
|
||||
const { container } = renderComponent({ pinia, props: { isCollapsed: false } });
|
||||
expect(container).toBeEmptyDOMElement();
|
||||
});
|
||||
|
||||
it('should render empty content', async () => {
|
||||
const { getByTestId } = renderComponent({
|
||||
props: { isCollapsed: false },
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
it('should render empty content when instance owner but not connected', async () => {
|
||||
const { getByTestId } = renderComponent({ pinia, props: { isCollapsed: false } });
|
||||
expect(getByTestId('main-sidebar-source-control')).toBeInTheDocument();
|
||||
expect(getByTestId('main-sidebar-source-control')).toBeEmptyDOMElement();
|
||||
});
|
||||
|
@ -76,10 +64,8 @@ describe('MainSidebarSourceControl', () => {
|
|||
|
||||
it('should render the appropriate content', async () => {
|
||||
const { getByTestId, queryByTestId } = renderComponent({
|
||||
pinia,
|
||||
props: { isCollapsed: false },
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
expect(getByTestId('main-sidebar-source-control-connected')).toBeInTheDocument();
|
||||
expect(queryByTestId('main-sidebar-source-control-setup')).not.toBeInTheDocument();
|
||||
|
@ -90,10 +76,8 @@ describe('MainSidebarSourceControl', () => {
|
|||
response: { status: 400 },
|
||||
});
|
||||
const { getAllByRole, getByRole } = renderComponent({
|
||||
pinia,
|
||||
props: { isCollapsed: false },
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
|
||||
await userEvent.click(getAllByRole('button')[0]);
|
||||
|
@ -108,10 +92,8 @@ describe('MainSidebarSourceControl', () => {
|
|||
const openModalSpy = vi.spyOn(uiStore, 'openModalWithData');
|
||||
|
||||
const { getAllByRole, getByRole } = renderComponent({
|
||||
pinia,
|
||||
props: { isCollapsed: false },
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
|
||||
await userEvent.click(getAllByRole('button')[0]);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-node-dev",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"description": "CLI to simplify n8n credentials/node development",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
|
@ -104,5 +104,12 @@ export class OAuth2Api implements ICredentialType {
|
|||
],
|
||||
default: 'header',
|
||||
},
|
||||
{
|
||||
displayName: 'Ignore SSL Issues',
|
||||
name: 'ignoreSSLIssues',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
doNotInherit: true,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
|
|
@ -51,11 +51,11 @@ export async function lemlistApiRequestAllItems(
|
|||
this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions,
|
||||
method: string,
|
||||
endpoint: string,
|
||||
qs: IDataObject = {},
|
||||
) {
|
||||
const returnData: IDataObject[] = [];
|
||||
|
||||
let responseData;
|
||||
const qs: IDataObject = {};
|
||||
|
||||
qs.limit = 100;
|
||||
qs.offset = 0;
|
||||
|
|
|
@ -123,7 +123,7 @@ export class Lemlist implements INodeType {
|
|||
|
||||
// https://developer.lemlist.com/#activities
|
||||
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
|
||||
const qs = {} as IDataObject;
|
||||
const filters = this.getNodeParameter('filters', i);
|
||||
|
@ -132,11 +132,11 @@ export class Lemlist implements INodeType {
|
|||
Object.assign(qs, filters);
|
||||
}
|
||||
|
||||
if (returnAll) {
|
||||
responseData = await lemlistApiRequestAllItems.call(this, 'GET', '/activities', qs);
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', i);
|
||||
responseData = await lemlistApiRequest.call(this, 'GET', '/activities', {}, qs);
|
||||
|
||||
if (!returnAll) {
|
||||
const limit = this.getNodeParameter('limit', 0);
|
||||
responseData = responseData.slice(0, limit);
|
||||
}
|
||||
}
|
||||
} else if (resource === 'campaign') {
|
||||
|
@ -151,13 +151,15 @@ export class Lemlist implements INodeType {
|
|||
|
||||
// https://developer.lemlist.com/#list-all-campaigns
|
||||
|
||||
responseData = await lemlistApiRequest.call(this, 'GET', '/campaigns');
|
||||
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
|
||||
if (!returnAll) {
|
||||
const limit = this.getNodeParameter('limit', i);
|
||||
responseData = responseData.slice(0, limit);
|
||||
if (returnAll) {
|
||||
responseData = await lemlistApiRequestAllItems.call(this, 'GET', '/campaigns', {});
|
||||
} else {
|
||||
const qs = {
|
||||
limit: this.getNodeParameter('limit', i),
|
||||
};
|
||||
responseData = await lemlistApiRequest.call(this, 'GET', '/campaigns', {}, qs);
|
||||
}
|
||||
}
|
||||
} else if (resource === 'lead') {
|
||||
|
@ -277,7 +279,7 @@ export class Lemlist implements INodeType {
|
|||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
|
||||
if (returnAll) {
|
||||
responseData = await lemlistApiRequestAllItems.call(this, 'GET', '/unsubscribes');
|
||||
responseData = await lemlistApiRequestAllItems.call(this, 'GET', '/unsubscribes', {});
|
||||
} else {
|
||||
const qs = {
|
||||
limit: this.getNodeParameter('limit', i),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-nodes-base",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"description": "Base nodes of n8n",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-workflow",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"description": "Workflow base code of n8n",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
|
@ -1116,6 +1116,7 @@ export interface INodeProperties {
|
|||
extractValue?: INodePropertyValueExtractor;
|
||||
modes?: INodePropertyMode[];
|
||||
requiresDataPath?: 'single' | 'multiple';
|
||||
doNotInherit?: boolean;
|
||||
}
|
||||
|
||||
export interface INodePropertyModeTypeOptions {
|
||||
|
|
|
@ -1601,6 +1601,8 @@ export function mergeNodeProperties(
|
|||
): void {
|
||||
let existingIndex: number;
|
||||
for (const property of addProperties) {
|
||||
if (property.doNotInherit) continue;
|
||||
|
||||
existingIndex = mainProperties.findIndex((element) => element.name === property.name);
|
||||
|
||||
if (existingIndex === -1) {
|
||||
|
|
Loading…
Reference in a new issue