1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-12-17 23:27:48 +02:00
This commit is contained in:
Laurent Cozic
2021-06-26 22:13:38 +01:00
parent 05e4b32d9b
commit 1bf17a6d87
70 changed files with 909 additions and 212 deletions

View File

@@ -1445,6 +1445,9 @@ packages/lib/services/synchronizer/LockHandler.js.map
packages/lib/services/synchronizer/MigrationHandler.d.ts
packages/lib/services/synchronizer/MigrationHandler.js
packages/lib/services/synchronizer/MigrationHandler.js.map
packages/lib/services/synchronizer/MigrationHandler.test.d.ts
packages/lib/services/synchronizer/MigrationHandler.test.js
packages/lib/services/synchronizer/MigrationHandler.test.js.map
packages/lib/services/synchronizer/Synchronizer.basics.test.d.ts
packages/lib/services/synchronizer/Synchronizer.basics.test.js
packages/lib/services/synchronizer/Synchronizer.basics.test.js.map
@@ -1487,9 +1490,6 @@ packages/lib/services/synchronizer/syncTargetInfoUtils.js.map
packages/lib/services/synchronizer/synchronizer_LockHandler.test.d.ts
packages/lib/services/synchronizer/synchronizer_LockHandler.test.js
packages/lib/services/synchronizer/synchronizer_LockHandler.test.js.map
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.d.ts
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.js
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.js.map
packages/lib/services/synchronizer/tools.d.ts
packages/lib/services/synchronizer/tools.js
packages/lib/services/synchronizer/tools.js.map

6
.gitignore vendored
View File

@@ -1431,6 +1431,9 @@ packages/lib/services/synchronizer/LockHandler.js.map
packages/lib/services/synchronizer/MigrationHandler.d.ts
packages/lib/services/synchronizer/MigrationHandler.js
packages/lib/services/synchronizer/MigrationHandler.js.map
packages/lib/services/synchronizer/MigrationHandler.test.d.ts
packages/lib/services/synchronizer/MigrationHandler.test.js
packages/lib/services/synchronizer/MigrationHandler.test.js.map
packages/lib/services/synchronizer/Synchronizer.basics.test.d.ts
packages/lib/services/synchronizer/Synchronizer.basics.test.js
packages/lib/services/synchronizer/Synchronizer.basics.test.js.map
@@ -1473,9 +1476,6 @@ packages/lib/services/synchronizer/syncTargetInfoUtils.js.map
packages/lib/services/synchronizer/synchronizer_LockHandler.test.d.ts
packages/lib/services/synchronizer/synchronizer_LockHandler.test.js
packages/lib/services/synchronizer/synchronizer_LockHandler.test.js.map
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.d.ts
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.js
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.js.map
packages/lib/services/synchronizer/tools.d.ts
packages/lib/services/synchronizer/tools.js
packages/lib/services/synchronizer/tools.js.map

View File

@@ -17,6 +17,7 @@ const BaseItem = require('@joplin/lib/models/BaseItem').default;
const Note = require('@joplin/lib/models/Note').default;
const Tag = require('@joplin/lib/models/Tag').default;
const NoteTag = require('@joplin/lib/models/NoteTag').default;
const MasterKey = require('@joplin/lib/models/MasterKey').default;
const Setting = require('@joplin/lib/models/Setting').default;
const Revision = require('@joplin/lib/models/Revision').default;
const Logger = require('@joplin/lib/Logger').default;
@@ -44,7 +45,7 @@ BaseItem.loadClass('Folder', Folder);
BaseItem.loadClass('Resource', Resource);
BaseItem.loadClass('Tag', Tag);
BaseItem.loadClass('NoteTag', NoteTag);
// BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('Revision', Revision);
Setting.setConstant('appId', `net.cozic.joplin${env === 'dev' ? 'dev' : ''}-cli`);

View File

@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
2020-07-16: In the new sync format, the version number is stored in /info.json. However, for backward compatibility, we need to keep the old version.txt file here, otherwise old clients will automatically recreate it, and assume a sync target version 1. So we keep it here but set its value to "2", so that old clients know that they need to be upgraded. This directory can be removed after a year or so, once we are confident that all clients have been upgraded to recent versions.

View File

@@ -0,0 +1,10 @@
id: 049906e6805e42ee8794a4aec9d4f4c9
created_time:
updated_time: 2021-06-26T20:08:14.685Z
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c200027c{"iv":"n00mA1fNDl0q5XwaVFHbBQ==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"MFSpyyISsMiCFSvlyAUS9VjApB/wPq8Gfx3gf4mjBjLgbNMirqrqv4jn6BMB7ZjQN2rzAo0mi0zlPiAkWYyOBiEuYCUE522ZInW5B/aXmdk5LMCSlXNEXYq7MT46ySKuaITzuDfrsrwqHwZchxWuK/wK3QTcCifZmuu80kUfCzIhx7gVfaqvhbMR246qCa8h5toiWESd0MetVgnwXfadLOGrwc50J8Z51MfBDTHT/Zxf/1f3AO8x9ascsXWesB1d41jINf2Uhuo0j4DoRawNIIhOvhDywTOSNo2ALK4SJeWm2rK83s2/nF9vaxcRokJRO7jSfdcMorqBdxSoww9G2apvxs2rJT/yVpGNlhJJvBhCAFlt8u3MIOSxop9aXqujGCR0aT2HQ2AdM7X0IgDZJXoUKODfdUYim4MbvHbXmWfk9vG8izDF7fTu6zCSLCXThXOYI1enTHByTRf35aJI2RbroMgJHA0QIorOPWEoEML9wCrKDKhZ"}
encryption_applied: 1
is_shared:
parent_id:
type_: 5

View File

@@ -0,0 +1,11 @@
id: 06d8599d079e4bca91a9e8e6233ffca8
note_id: fbad304e76454894a44ac57fb46c8007
tag_id: 049906e6805e42ee8794a4aec9d4f4c9
created_time:
updated_time: 2021-06-26T20:08:14.686Z
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c20002d8{"iv":"UxbbBkb0easQ9ZxLn4SNUQ==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"poUjWTnldGEm397xoU6BcqaIM4G/Gz+4ZtAhsN3vLgWYQq4Cf+nXDUk8vCWAuFBkBWKDTfEnFv4cu1KuFq2mn80H/CdtoDLeJqpyTQ/bKL78ZdWtwKjfHGiJCOSybu8XRT7WHf3jnjQeq+549YyoOCPYcShBPEX32Sgoc7m5AmbSSgNculx9DXMzIUupAaAaTUlp4oxOMLR9RT10E+oNou9KQdt+/HVS/8Yq+ZvhcUfzecwwvc6gdSoQi1GMKweBYuYU7f6otfaqsYQ5WrmRS3JOROa4YtA3LHwdXGiAu1EvOyCYgB+OQ+uMqUyFoaRJqoJWe3gjSmnR5Cx8aYRrW5MtWy9QRWz0w2bTJT0I27w8nDyvzyGMim6LwXyxYv36g7tD8uFmRZsjMcxLAMvuE+zx5dEdQR0IcCHjREDrU6qs5NjcGnvrneMuUcWX3g5Ih9q6uTtxkkCTXB5CDgY9TFjoBL7osObbe9y8JGAlPFkCbcOjgeIzHxyDbYpMuCA3/SMBYOu41Uh+Dhijj9f1D2y8LDDvKePGHAHH/dKEQdqLvmT+0NovZmc6D8+gj+LLJdqaxTSv9l2eRA=="}
encryption_applied: 1
is_shared:
type_: 6

View File

@@ -0,0 +1,26 @@
id: 1cbed8070dd3431bb1d6f341c2f6fa9b
parent_id: 3903d5125217468bb781c409fe6a693d
created_time:
updated_time: 2021-06-26T20:08:14.688Z
is_conflict:
latitude:
longitude:
altitude:
author:
source_url:
is_todo:
todo_due:
todo_completed:
source:
source_application:
application_data:
order:
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c20004ac{"iv":"3HpsKm/uN84zD7tg1Oy0rg==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"zQBIUOWeatdlVug1AZOkn2oO1htfQHbmokWAeMajMjmMQ+S87gZNOrTD7z3Rnfz3EMAakSunUrdmoPtNXl7Wwgr6TUeBslhxcBoHKEBUp/xPdvFzaH6IX3gMhQy5Sp3SxQia8S3aitS/vWdZFjk6pEE0B8TtVoUB4s51ofAm0XVemwHl/SejkbG4sBXasEZHI8xDOgTywbyYVn1FGLsHwFlhG1guj8omXBHf3c9bASSpyqWqIxEyTLrMHJlKPUzQR1Ezt8eHZwiW5AUhocDHBD7AdZlrNvC18PjMYT+/w8ZrwZ4+cLVV0ZDR916E1jdVrcQ7DtsMgdddUSFoL8UMi4/if0IvhvD5tT2W9fdH/Ln7tkVyedRkWh8ylSvkq/1e+pQxca+QEawzcDmAgrUi3oGq1BvAikbDJS+MF2ATATunybqboEhnb0crlDtCCVh2fUUYyCqt2KEqe9r9X0GBympieugI1+jzFeoCyReGkaTIgc5tF084A++8gU0gXBj1y1OZqa3rvaBFkq+8PHWeR8aMwuy/PG69wPn409ZP39dCyl15J83tT10r4v1CMy+7EMYS70R1KGRmfzm1oA1SxpcJipIJEr2TOxD2jdjHuuKeNljtiFFvasQeDv8EMzSIu2d5952tTJRong0+qpXtH5YA+WNavsHYGbmQ7rsrnjUAdslIv+R6A4gdEtT26xeo86KtFWZKxCeGRK9kXBsrsXCE7v9m3zNPENet2EM3i+zs4PIZ8Z5XCiDH6cFokeBUQM9G33I7DpIjmh2rZoy6mc6bwXxjeobfx3fmvUYIKtmRfh+ra0kBvKYIDe9LR7pj0jkH4seXvwyjKtND8+b/MNhGaHGI6jTRvhJl3dX2IZxkHh54r7WYzUgCdsp0SNVldm218rlB/w1eVgs/pXWzUr4nvv3VOEAQzkok8MMJPEYz/MxjB9EAR2jVyjQGY8p74HHD+gB1wVhI2UJrnJCbHXWiRqcEW4hGbo7AFjelXRIHt9slv4eCoGAdWmaYMYqe0cgECs7X5N0QbCSRthMmDIpup3EDVl2L8Q0E"}
encryption_applied: 1
markup_language:
is_shared:
share_id:
conflict_original_id:
type_: 1

View File

@@ -0,0 +1,11 @@
id: 3903d5125217468bb781c409fe6a693d
created_time:
updated_time: 2021-06-26T20:08:14.557Z
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c2000298{"iv":"MofHz+Hj0PN//BzBBqjBCQ==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"Oq08E7jXlTbPpoAAA8kB+XJ+9B+J14j/cD99EkgXpfgRS9VC0uzk+EkgACaGc5l/5cIPSKDSmKpYSXabfjXily6ju0TI+YJp9atwdOl+EfFBhW5eVOtwhmGOXjfzWvKw3/Js1vUi8gSK1j8WTAEI3y0MpCbPOHb4dDu3jJ0f6kI7hAbjpd4lZxiLPgW4D2mkZjK6hUmeqyBTJrAOa1t5DrMukfLy5g3842VziZafw9oj/b6GdN4KhEHZwHs5P18Qdvjy/738rW+IYwGHGsMx0y9rq4Tc3o9oC71FWVD8BuWIr2bBnYUH6mDfB4EbedoSAc/G1XXn6vZAAY4p/iIZkdjYHGVfZHAX6aIzHBiatQXvhFnhefUqR6eGK6lvKCOVj5yEnLjWgZthIiYftwBM4BAY6XkEL1UZoJtJ8j9ZAFH6VQGzhll+7VJL8Snhbfs1AIDBwYQswxYE43dJ5I/N6TojZ04G+Z+7TXH9dslK24F9eIvk8xBhanjQk8z9Iua7EtizgberLQKF9Jk="}
encryption_applied: 1
parent_id:
is_shared:
share_id:
type_: 2

View File

@@ -0,0 +1,11 @@
id: 4714bf1e2bc04edfa32c456bdfdb674d
created_time:
updated_time: 2021-06-26T20:08:14.559Z
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c20002c8{"iv":"BZ3ouTPKUeAppquqkqJkZQ==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"oVr2Ai8po6tv8ciPhYGJsNlMpqH1r2lk0G4R/3/Tn093Pk0mVmaAwcIWjrlk6sOTvrA49WZDQrQ9fD6gJ71tfUrSr6OATQ2pnsF4xqIls0GBbioHMhKyMMzrIkvFUBS28qKfv8Ojhc7RxMOFZBseDXZO0E3ocdcxfdOzF0IskRnvIzjTLOJKyHsHe4mA5MBTvWdbXKuO96/JJ/ldLICdlGGVaDyZ1ToLnuww3T+1KGEue6t4ddTc8T9fQYRdeFciPJqGPw2N5p+VjMMA0JK4VbJo+gH3fihwpg3SJ5apDcYRcUMtpnJvWi/hPeqJpgjInn36so6CKN/2YZlqQQTr0tdK9Ko9SVnycsDpubfirpE/eXADovNBO2kLZyn0Taq1+MXbtEaLe42kolQ/9dL6TxUYztwxc4SR+3oM+UXnXwFUvW2lHDQXNLqaojm+Rjet4Nu+bksgumJuhnUmc8FB5LdVLFRPHvmTyqZP8TpLN7h0yfiDW6wW/yQ1R/U7KoJODr1hmRp8ym32H2YAZPK4fyxd5pSE7T3wIF8SRt8elX0HrOwHgNbof09mxxkzfw=="}
encryption_applied: 1
parent_id: 3903d5125217468bb781c409fe6a693d
is_shared:
share_id:
type_: 2

View File

@@ -0,0 +1,11 @@
id: 53fc76b1c3a94e1dafb98bfac07af69b
created_time:
updated_time: 2021-06-26T20:08:14.692Z
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c2000298{"iv":"lu52Zcf4k4Nv4e/EERw7JQ==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"YpiWeReRHJY/vIPAjvR09YCwVWC9J+Yn0n6XN/+EDt2qYAzPOKh0QLzuZX9IR1k4S47S2NcmT2DEveZCYAwg9sIiyghxd8yL0+qa+nZUvb6mdSa1s/zACUZUjlsudi9lduStpI39Nhig5OamFgrpkk2iypNOMsFqjUGlNoUc+NPndu0V80/S/Fjoeca+xqgDTbdjxlsgMtq4Rk1KfVcJTCGjbtWoU9jtsXu848iPXTtOZToeEgrbTjSVqBGzPU2v1NEpj516elKngqa7Np32/WrkQAI4PIqk795PuiVa9r1GvP8XGiBrxek/Go/kHOcg0oozx5VvsSdRkP/q8PxIYjLrZ0+3VWipgmoTGTe+8Xeg8fsF2IE0c37jGG/dgH+8PhHCUjqSS5A6uf+Z60UdPky1XlzL+MqQ85f8YzEcy9nB22NvI517lKiT9CKeaK63Th0je4qRw1mrwKzfZdmCNGaraIXnhhGksXmROFVJbVbrj/B12XCATb/qGYFwHfAvt7qgoC75L7oZGsU="}
encryption_applied: 1
parent_id:
is_shared:
share_id:
type_: 2

View File

@@ -0,0 +1,11 @@
id: 55fadfe8ecf9411da4c0e842175cd9e1
created_time:
updated_time: 2021-06-26T20:08:14.560Z
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c20002c8{"iv":"u0WT+phSfRQogAmxUiRHGQ==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"95XmsRl6+WnBbR0Dfjb8rNtMzUj9THhLm5LdixM5N/18ZkQBR2BFvlcyZq5u+aUsdJ+ZMCUXf294xYb1TWEr3QrYTGpuOwZX42HBksu9IAq5QjHfMh6Gp8hZEHKlO7k84G7i/mvsH7aanQ0EBALoRuxvd3UMZN4JTR6lXOCpwu+H/P/mLErQBx8iU5c4XI3or3fmAQGuhEa4K3S+KIwEbXZT6B3BkDtGQrMk+2HxTB5E2eb8hAnNFsA3zEh5jaYHLAkgmkCVICAck7jtRzryKvuK6T50f4120hT6/WwBKdnqiXjMcNPyVHvNr9k0xkFuZuxIPzp0MCs/bZvB4XCy0fMNe4bOOgpMkiLCyRm32GJe/QXfnhLCp2SWKKnwcs7BbflPeiWFuoFW9zdhLVA9ixfaj0CBLTvmDpecNMaz7pifa5ZZz+/MFXz2Rwhm1sj/DOQpcGtAbWpg7nh00iD52RUY9Lf8LvyVTvDEDSp3iJknF9LJk5Jebxy32O+iOwFnta0twfhKzdaEWp5cy21jDgcWE6omo0renuQGP+p3AUoJrf8nZVGF0YpYBuikOQ=="}
encryption_applied: 1
parent_id: 3903d5125217468bb781c409fe6a693d
is_shared:
share_id:
type_: 2

View File

@@ -0,0 +1,26 @@
id: 77d3f99b018a4d448a9ac349d70d191d
parent_id: 55fadfe8ecf9411da4c0e842175cd9e1
created_time:
updated_time: 2021-06-26T20:08:14.673Z
is_conflict:
latitude:
longitude:
altitude:
author:
source_url:
is_todo:
todo_due:
todo_completed:
source:
source_application:
application_data:
order:
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c2000504{"iv":"yk/Rry9MdNPPZsseZVBOAw==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"4rIuv8fyTYKwx7vcWHTVhDJUN9spWapy1BOYFl0l1XcBGk8sn6kFERBclrDyPgpXOYpS2TL4OOAtZpDYSf1G1HfQGGIdE5DQY8f+EMv8/R4y/iGj1SBnJTUJYT9MgBnz406wWTfI02VV9bGgNNtyVqGExSidl8Te4bu7zIE4Hk2hPipGs4XdZxQCmrpmw80ZcqabErB0Il6rP0VmvSHvnwwcCBO4o8LQWyYD5EdqDxRAIe6XDyNV8sAfsOuOZXN0IxQeggFSYBAg5KCZpHmpWwRXNGkmJKxgwMKunHsw32+8yz0/nSXTjs/tLgxU7dK30JC2wYUt0zdWuXJHzUYNH9U4Y0Iwfck1ILC3ErdlNT+Xn5Dq/C1fAD9tIuvrHHwBXJRjuS0pmI8BRTo4fVFq19sJqjDtNcbcubZnPN4S3e5o/nY8r1yZ7qfGj7H2+FKlYVtJYQqgnnadFUALn3dIf+4lfjngkHx8OvKbaBLt9AKxnusrbtmUtYvNEU+drP1+/DgTMnSZtq8vl53v6lB5dJWhCt0df/gPlHHTkWybBjFCtA0E6MT50/6oD9P5lz4+CKCtI/ICuYmgoOWUmHGrFSJy/WI0rfg9oh9MZjW8VYZWCljgbs09N7AOF8jlSC/7+3/XZS2rU3xLcAG2cR9Z6EBuHNi0aANDjL7Z5zaJyuoBUwkD5H8ZmzycjTuEl+B5kyQjrncjvTCaxPToOiWQ0Dx0pKWVCYX96W1LrFTaW+mqz+Yf/ds9lROaytlWy2B+smYhkh3PZSBVcwfzrWmVCjs6dfJ9ymiNbRHISDtVo6lK77/YVFrzQ2IWnwoc3jI53WjzGGQo0nyKosq7FTV4puD8L7gG3pw+Mj9uYkafyhY8bEKJjTO7N2FOJfxPXq/FhSmWaxVOOABv+wTnLA5jc8yBbRPUz8mYMZDiAlfq86i4NSmtaBWyrkEOjAeyhEjOHK1Pg96sE0Xma16Q672TcKusPJw4UdwpZ9GjitR3b8s7+jCBr/mP/furKHTge6LPNvKMjZFx/r3EQ26GXtygLyDfy1KPVWnCv2gMwPLDMtC0tiZTcdv/LzmAXo3MwFo2y1PWC/krEXXkLaWV7d8FIMp9VGfhrcxZt0MyiW59ANuyM9bOBXZets8Avk/r"}
encryption_applied: 1
markup_language:
is_shared:
share_id:
conflict_original_id:
type_: 1

View File

@@ -0,0 +1,11 @@
id: 7ac75ff5191049daaa48c3611f913e9d
note_id: 1cbed8070dd3431bb1d6f341c2f6fa9b
tag_id: 049906e6805e42ee8794a4aec9d4f4c9
created_time:
updated_time: 2021-06-26T20:08:14.690Z
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c20002d8{"iv":"q3o7YEgiv8EHVC6fQA1caA==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"4ePkY/4wiSOreCbWW9ln0/GppkSM+D0ONPYxBXdqiTv3M/x5gEiXHTYg/J2+XnkUowT7prxtnktw3wh5wNf2LnZJV9WFO79Z0uBT1oVgv/Q/7VsHJSlA+4b79pUYl33e7YYeIV87fUTeESJe1YpDn2HzgFQ6eqQ24VUYJH6OQObubWBPFcUieecqXJCBkYmiJHP8d0XuKfUOtr0bGcQ3ZNZ4gTW35oAwHeIKRjeGsRXa0v8Ci68pTflomltk5C9uEk4blbJ/cQ5WVGWS639NXdz96N3DBbxZXUCZ6ZWKRY+RI6XvYKx4hTELtCxBSdXQmzSO/EzU5g9ncUPpKZLOATcXxiY1Q5ATfIqjvBdetr5hQtmniixi6gvmena62ycVXmqsZw9CU7Tjb9gBuetXl0JT14oF+6w9Z/r5abysYkLTE/cxwcGwdaXohiT6lkiMkyg/k5hOMwqXyKoHq++eonf6gtO8oOUXdTotkujNY/3jvCKxpscZIlwJcFe2kE654d0PF9gXdvptG8z3vH4UUYDbI2EQJAqtxwlvwG8mjYYNLhWmMdv9260n/0nDyuf5286cXOTeKgmI0Q=="}
encryption_applied: 1
is_shared:
type_: 6

View File

@@ -0,0 +1,26 @@
id: 84b9ed05499d44e58eb448c8a9227adc
parent_id: 55fadfe8ecf9411da4c0e842175cd9e1
created_time:
updated_time: 2021-06-26T20:08:14.680Z
is_conflict:
latitude:
longitude:
altitude:
author:
source_url:
is_todo:
todo_due:
todo_completed:
source:
source_application:
application_data:
order:
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c20004ac{"iv":"FhP7Z606mGzQE9mjCxYaWQ==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"ewBythIJ0ZCP5dHjWNQHaJR3YlDlIPFBT37XF94KiUDFiTuy2cD5vw/8laksPzgOM4cy4qAuW0uh/7gxT8bcFHb4XV4kXkM0HcohSkzmcUPUlSbm7YejK98Mry30i/5t4Jb+ZvLWmpTpl2nMmamjWCk5spd1iOy6lcHQK2JRzhCKd0SC7ZANyjzsLYPzZnfDIbKXKM3hjw94fMuAAjQ/rjFlFriijclvM2r40kqiMjusfc6OPPRwGOCefKUzPQfZ0lDD0CHrRN/WhQkePH/24zhRW7v/Gb70H410vz6F6oZ/A2vIWQR1mYZpETaRoCHGBSFQKdrm4ooAtDmws5pqH2i1LyMmqsvt3wnZssHhoLGgxBSWwvL31zMmnOdJ5wXiI26J5t1fynEMGxvl4T7KTDOgxPWEF1LU1DOeToo2kLB+Ch5c3coYj3psO8qhTwuI7tlMLxeZMLQrV7Kxdk0qeG1yqaI3zcmnLRfCWrJ3NUaaHV3V43GjD+/AWk/Q7pU94weTeQYRUyty0ZIt6X6chCgJE/TYKna2Iaxj71IqJxbH5x8gPgb4YBQKcBfU99r2TsNynFt1RAeykLwuBUpDxR1wk9B4s5/WbLFCptKSMWcvgMvm7o0SmI/H4OZgKQfIhVoGCZCZaXr4CLywwmbb++RD1lFM3afdQzOi00QZeeeWM6u7ZIGvSAHoY7hlsXUv86w1TI1V2vJxuwNgEh/PJFkzajqQY6D5Xf1HXzwZJc9lzYtnhPge3zHkgfLotUxtDCMv8eh+V8WvmbvF27/Crs1QQID2RWYQBpzKJp22s0fh2M448ohF+kXsTuoGiO8SLKvedvdTwN1C3EERy1HQDSsU7s8Ff7POHOIphVlJMDVu3ei0c4CdtiR4d9Oiwh3tJZ6Rhe/LBz3Oe24ZSuTjaoXTH2uRmtVXY84X7zkZzQB85INq+yarBUK+gvMvROwJUwgr9ZUfnBbQBn690P7nJCFSS/pwU8PxiC+baI0bMx0VSqemDy/qEp2RkH9FxbvHKXOwAWFCtDou6ChT8FENjA2zGq04v1UqUEuX"}
encryption_applied: 1
markup_language:
is_shared:
share_id:
conflict_original_id:
type_: 1

View File

@@ -0,0 +1,11 @@
id: 8da3ba3ee84f4a938c9df1e05253515f
note_id: ff770ee627694f9e9ec08f4a218029be
tag_id: 049906e6805e42ee8794a4aec9d4f4c9
created_time:
updated_time: 2021-06-26T20:08:14.802Z
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c20002d8{"iv":"WP147s7xzhqGVoqB8MPMow==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"OiEdFHraFYd8dZ5al6fX+Q6xlx+A4gW2qV9hRTzvraW05RqBOopjnzyD3JxTW/3zkgJTBfFthGquKraThRFS9NvjPkBdiKQP9gsNcSeYAIBgUiNUMzV69lqpX+OhvWWqbHw6Od5TI2beMp62/5DP+AiX7DoJS1O1f0vp9ZAIxd7/tpcX55wVp0nxGScPFXmWa8YK46qH3jiuOl7y+685//VFtrBRsaP3RLbZDcCyK/G+++eoP0uJvH5N3StwSvHYl0Jhahto0jguo+SRU4Y7GU0CIbOZ9Oree7UPkeqLkY+rTD0DZjhcqAV4cDFaza24AY00bpZlLTBWQ/IJim4jKZAbUyLAToAWH7tsCG39HL/QXoVxCxD3qglkSz9NWUyKoG8NKEmVDotH0bcF1qyMF9R8qj4q/Y1gH5n+AJ4CF+qa0Kd9jBOqk1RW/1brVs5tyVakDuARO5jtobOviIuVqj6dYYVybVSLxxwlIbEJxv3R/Wd85g9+tsJXwveeVXKHTueCCVwYSERb49c6uDpe1NzfU3LTKCPkwk8fu+es4L1uWbfpP+kSbi8+5qJF0k34vMIe4FKvNWZvzQ=="}
encryption_applied: 1
is_shared:
type_: 6

View File

@@ -0,0 +1,11 @@
id: 98cdf9cf320742e995fb43d60f3293a5
created_time:
updated_time: 2021-06-26T20:08:14.691Z
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c2000298{"iv":"7QhZftaIny56x2hpBml9fA==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"hnazZV12stsBUFLOObCr4PvR1ao3Nq4SHLcJQrsSUOKT71/CvSgTbTY5tzQPhEwmDUFuauxj33/n1sg+J4oF6E0Nknmx5FIwtm1jOLHuPdOSFU19MWxE79mctVArAYApxns3Hwqi+/lv7P/tb78Uq8TD4ZzCcfIEkfh+/6pyRSNGURJ827J8hP6rSavClS7eoBa2ThOLk5Wyi7xxs/JnG4olu8BvuSlzgDVDaWJ4NLUhnWP025xUTbj7WPFXzifnXHVzmOTB6syOlfLPLugFsdWAle4MktGOx3TXEidTwB1egNdNh0GCIzG4hrp9Z1k05w7dgBL9s8eE9SkqWLVVCItUhqiJWCy7ROVyHGvqhNdh3kvFWcC0NtlWR3TeqerypCPuJZeZ6e7qgLDYvaAjTsegrI3gGpDfdXdofqmmC5q4PSneXhIqrKqsvrhgiEFliHATaIXcd7H9C/2NyuZaJIeIzSHF+WKFt0KV4wmJJMV4jmPU+u+TAGsTquGk9v2tItUhzL6w+H6Zttg="}
encryption_applied: 1
parent_id:
is_shared:
share_id:
type_: 2

View File

@@ -0,0 +1,11 @@
id: a80f47ed538341c39f5364a8ac04ff09
note_id: 77d3f99b018a4d448a9ac349d70d191d
tag_id: bdbf83546c0a4cf3a38c103595d62ab8
created_time:
updated_time: 2021-06-26T20:08:14.678Z
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c20002d8{"iv":"NRKiGSTpI5RKLElU8i1nYA==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"D2se1ksArb7asKOOPQMLxJ5qZbhGLHjP5aEryds6WmxYGheLCxKUOiPi1BkEr8SqrQu4B9+wLd6Ra96ARHq6vT23SE3GydNvM9vLU4Jdk54db5Dlv4z3i/WD6hbcpo4VboBO3mhXZV46kgbLJGAgCbtnQb3v/10/oeLfeG3z/zM7+9ByZ53HuMtUJMIbITuST327Ozk34X5a/YcUMTpHXq7Vycx/ofM2PQUCI1E25IgPDnw/Hx4qyW8U/cVn+XfCj051PXYgYhtjAypEZtzntKuvMF5gVKHlA0J4bCONHTHNuMhXs5u1o3MQo/XOP9w/WZeYAh1pmKNDaLyRmsmwZ3j65eTMUAPBO1LRbZUUHS5HwGh+zYwxm9zCTbiuYOu0skBLqX2RRK7IhpuGszxGIr6T+op6gnXiPP9M+89LtbqYEaX0sgs+fwuh+uag6420fxzrkCrn1d972MEn/0GDkGLJAyIpOCiS6xsyWp0AlbD79g86u3wiE3s8p8d6uBQjwpwlRxa5BZEQeZVoqpsap/uRvYPLJNrBPnoeozocTaA3o3GZvqNe8S9YwWX8n7y6uIC6kd+eZ+AmeA=="}
encryption_applied: 1
is_shared:
type_: 6

View File

@@ -0,0 +1,15 @@
id: aac6854be54d4cf2978855c64ae13fb3
mime:
filename:
created_time:
updated_time: 2021-06-26T20:08:14.798Z
user_created_time:
user_updated_time:
file_extension:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c2000320{"iv":"Uj3j/7TEZVAdm1X3uLHCQw==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"aajrSBJmpB7WibYSikGWqrinofwx0MVeDF2uoD3ntzFwOAY8QnPhvQB/Kn2Y5ndGFbHA0NeuUVLYd7bwt3iAjm3ZWtEh5U/vXsKLnk5iIjaQyGYw0GkCuxPvMCkTEvDAfgBHjnzavpRTYFWqM1xDCmzSyPEqnOsN2DkH3bYD6vXN1rehulzSQzT8fm96jQe+9qaXpyYPVd9lukYMIGJ0vJgk+LuwmK5DLkW4mD0smQOnF2Copfek2HxntkpykBMIM7cbzSzJeyvAc8G+nZat/ZPKBItei2jhrcy9VF4mOUAkhsl4yFiLLf9anJEMX73IADAAsoqiHNZVOWMYogXIbOweVmfWcMQIiCQWIQMfygakuSxOldER5/mV79FgdyS+1HdVPDbf3z513eRhejMEzNdtfBCuI01YQcnbe3K1xQLJVI7VEp3DPbPBLL4Nb67U3sthVgNKd8Ow0uxVDQrDpIGYEIQl3ssIbvt1gZBzZbfiTkKSRAHAgZr35zDBV3XTdNBNWAmf0GsNnaNnkfuzIaby3Ov7lfp2JjANeaKlTB4AsculgiUVjXqqWumcaPG/++dzb/0lyuVwpdkJG2/uvQmdDeydueoJSlGaq+5hJ2GCHuW+DI7Z2leWnQp/+rawUeCxHvR4Hkw00usBxycHWy4="}
encryption_applied: 1
encryption_blob_encrypted:
size:
is_shared:
share_id:
type_: 4

View File

@@ -0,0 +1,10 @@
id: bdbf83546c0a4cf3a38c103595d62ab8
created_time:
updated_time: 2021-06-26T20:08:14.677Z
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c200027c{"iv":"LTc2Jqoc462JCi78j8WXnQ==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"VicUNDsaZ7l0mbA2Vi8hTiekMhXsBjrkZR7Idq5YsNcqGhmfmD3+ELKMI1JtqAfkWoplVt0pbBe3i1U30PlSaDOghHshB4y8AJNQZeOYhzAP8w/ND/aMpogfYBM8MgPsxROWM2803H5RP6roDH67FdWLA6xmbUeY53ZVN9h/2KyaJ4LzWrB5NcdjPtTGQB+ynU91mZCN+Z3KjpsBtGXm6DqCxqBunOylxP+WMzE9L2xTUki0ismcNpPejGlNYmloy4Y5f+0ok2EQMdQBGMiS8wjGdmEqJ1zudquS5ITl5rdWwOYDTUap+VMjCSOGB+EQ4a4r/t7xgJnjGuccS3KPnd4gyjw8a+QwWGagzVIFMb9EZIzH5Q8esUFYvdFPaxyk44B7l4rMr725nRNW6cYQ9Kld7t9g/CZrx0aFBQIgRcXeCjcf5NgZwN4hdIJ8HCQBVxDnJszpp4DBLQ1im9lFGQkseQgcbRqyk1j4Bt+HX9JyOcG0nKZQ"}
encryption_applied: 1
is_shared:
parent_id:
type_: 5

View File

@@ -0,0 +1,15 @@
id: c330509f12de47cca64caed7cb7e069c
mime:
filename:
created_time:
updated_time: 2021-06-26T20:08:14.671Z
user_created_time:
user_updated_time:
file_extension:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c2000320{"iv":"DMeGySLRqW7ZDvJVJ1XLIg==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"qGlwrTJM5ec8rHhMi4iMZKCrM1Bz6VnOSHljhLH0aPbrdiygDPbXVlplRpvret8U+i3NbMqy3VmfiL+mQl2Bfy/r4PChTRrNSgPqqdC+D8butSDUEZkHzld2KYgR4hwD+Fy3e+zU40S83rF/XnH1qUrqzPSuS37em+U7AI27bWgXNSX+mNJZ4xUNYLicfwLInqkIGcmnsSbgUDoEkdoq04U9fTy1nHXBL09M6wmLySBNNLAY/YwqG1nFoflSJ6eMH0SXONpyGwvpSlwo1vx7MQKLLcI7+KgEh/2ujCYfBpgyarsqNJN74YqC7lVEa/R9XECi5scJ+2TbTGOPvh0p2R2EFlq5pHp2Y0MMIwrMyzI/iDpzvMMUjPOQ89nsRhSA9ahzS6TtHIcfs6V0i5jwvcC+O4+sAdxnWN3RV3gvyLUb9CoYXHhBvLfxZ27XurtP39UbUZcUP0QHKEAUtcD8LN87eBujK2YIDAA0T41IZUQoxvZC1J9RvyIGFKqy9ELdD1dQ7W0Fh322IWeruH2oy2NnSNF/Hcikj5ggV85G6vJ4bbyvv7pDqXPa5yNs703Di1tiHxtbO8Yb89jWlNvIpIFH5knN7kRMJABWdyzeIFegs8KMuOa/v6ji8iTCZoh1yuAZNX7Fre+voY4aQRYdgSM="}
encryption_applied: 1
encryption_blob_encrypted:
size:
is_shared:
share_id:
type_: 4

View File

@@ -0,0 +1,11 @@
id: dba25a5bf3534de39854dba8a4ec5351
note_id: fbad304e76454894a44ac57fb46c8007
tag_id: bdbf83546c0a4cf3a38c103595d62ab8
created_time:
updated_time: 2021-06-26T20:08:14.682Z
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c20002d8{"iv":"LzlH0FnzEw7HqzZ5ltEkZw==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"UazjD4iyPODeDPPOQdsdFEuofk7ZAR7s06kJvkopyTNLTf2vJUqZjdyzXgcr3ju+Nz8pTFnpgIWv287jzOunkqgobwqlHNKTw0XpBJu8Q0k2vGg59PTFOYanz4JlqIfglrXboqnjkMgGYdeIU049/g0iqXmA9xytmRa8JSWpUelThVl2UiRCQwynCrxV7rNtOnxO0v74fX22W5CT703enmScevMmEJpO2fLwIw98Z0X8VPXRyUBMBmBQygxLdKis7Khvk+hwuAL5nPUzqgLaPpWAvn+EZmI5nqqpk9sX0dYHEEnOOWkG4pyNxIItBLLY3W0sybFBwJt96yPuz/Et0WHGdiEjWL6tyDEcq6l5tfbrYI+rqwPxxUOcwWk0aVA+LZ9yvqsp4HBwr7fr92KyelxriPHdBIXBAJae4KI0FHh92YadUcH3Dn6V8WTYzUN1Xbn8NFeoQPPoHHAfs9gRcieyDTRHPlzYprTdyp9b5iBEtRjyZGgO/9b5i9ks8V/61tJhPWIimejgm2w2MdNGnq5APxejIMTRfjXP9hDuArzpdUdMEUKBPcpekR47OEoj7/d565yo/fbw6Q=="}
encryption_applied: 1
is_shared:
type_: 6

View File

@@ -0,0 +1,26 @@
id: fbad304e76454894a44ac57fb46c8007
parent_id: 3903d5125217468bb781c409fe6a693d
created_time:
updated_time: 2021-06-26T20:08:14.681Z
is_conflict:
latitude:
longitude:
altitude:
author:
source_url:
is_todo:
todo_due:
todo_completed:
source:
source_application:
application_data:
order:
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c20004ac{"iv":"b9azKpMJIWIEhajdeuWZwA==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"UfkxzVjc5tdRe5otTxuM5JK+7lftFfspCMKVh6bxJcDOcVZrbLCsM7diYYkOoGvMDdhSjM6BTn3bA/g69I6j/vG/1CBMhGO00fVgosMxQvuuOQd1kKg3U1Y+MUKDAaSlV26a/PgdZC0nce/0kWxThKLbjR3f//pp2CgY5qZCkLLEelpYU/T2prdA0oCzlczFYJb8kGArCZ74qzK00jpTOPR8E1ktYsmNoRZxWxmYKq3bghRzxdzhOtmwbfYyN3GtC8rz5ZZ5Rpuo4HKe3ZN6ht6J2ztHM9UwrwWG2wHbrbdxZXw2MC1FkQzLg+VnXN55E/GzcVAIqCjZnHzvlPE1EuCojC6XaEJ6wXp8qxYl0WnfUNERaoj93H6yHnOYppOYTNSO/TqGGm/AK2hf6zQinGjWRUsHxnNamfuIdcDzP0kv/STpWu29WkvYkE7kya5jpe3NVjH9Iu8ihe9iuzKtW3Z8t1YSXPk0VS/CHWFI1PAXttQH3MUQdq7kRZIfWnHR7EgVbcUYEYCOznIjO8P+pq1DUpV5ijzLtP3vRGMBt37NVQpBFeMCwKV+Hw1UNpkUO/GN+kZp6hOhmzmLmpDjcYr6/jlX0CjQ9vjQ/RM2VKlTVYb8aTDbH3hFb/fLjP20UtFGylk64lhlTaTa2iOO7WFe5rrdtSorKdNHhNG3upbSDvGPCTknF3LnDNg3I0ILIRoMRLGpvotBxhxHZ6Stxp9MIHi6fSA5RoU7Fg8QVK2X83lFzNmdxHKZ0yv3je5Lk3P+JcFawRNeo7PML1Ep++bwlmtmTKWTTKsgcXmX/6WE4MfoOw50Efc5WJQR/GU1mmWOwHa6PKeeG9uS+Jd2uwNQ0F/TQzrPU/M3lJA6S1Fosa2BsPVvQ2VgTHU8x4gB8LyKgw77ZvTzzVDmjGzqJMycLr82k9mHChgyW/dR3gNJ87u22ffgST1UY/mE1Paymlj5n5VpLPAO5twRQdAv4YWdRaDnBOKxWxmj/fwc9+LmUJF09VygbMbLN92bpdELQFIQQQEnCBjJEYr8pXxIEX6E1Qrj+FuUrF+b"}
encryption_applied: 1
markup_language:
is_shared:
share_id:
conflict_original_id:
type_: 1

View File

@@ -0,0 +1,26 @@
id: ff770ee627694f9e9ec08f4a218029be
parent_id: 53fc76b1c3a94e1dafb98bfac07af69b
created_time:
updated_time: 2021-06-26T20:08:14.800Z
is_conflict:
latitude:
longitude:
altitude:
author:
source_url:
is_todo:
todo_due:
todo_completed:
source:
source_application:
application_data:
order:
user_created_time:
user_updated_time:
encryption_cipher_text: JED01000022050e6c545903544ac1b08fe406d22155c2000504{"iv":"aQVeN4wYOd1FCLgM36F2uQ==","v":1,"iter":101,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4fhj6/6Erwo=","ct":"E/8zUIYScRYmac9VZhSk6elv+s774i92YGLSVyIha56RFs/2by2+35OinJrTtvtshxGbVC4SnZLYkwoJ2m93mZkEk7EWYAcK/i3CoaVeegNl1kH9+zSkOGtlPm5wmqmr0qOry59Jkr/BzfmV2z7ZxqAeUiTO3L1cIzDE7D7zLRriM4s9nKyuUE/8wKmg0/R/drUjU4TRR5u9JebZQzmG0ufSiGkiXHLEu/oDf6ZCZFHihoJzvhP3oCkm13vmWRgIBww7nw46Pl90lit52wL6YEW+9wt8gMRNB5GyCJq3kXRtyRx3jcErx43aPE2o5fRphuElkZoHbZ8PNVpJg9s9QwoPgyqL5XpHU1LQin2qlWQGQ4yFiMOCrVIlljpb35TyBgf9ysCIiClMxoh6ZzltS6o8bT0C860t6UCWkRMZVifddj0oq6XnmiHWi1dIgvb5zMZFahUQ0RcqrfTO0rJEMeH+brjRysN9cguoqASNLXdXqM+J1FEWHC7ESAaC9AV+SfXBz26cx7lptq1zK7ashdwkJ00wn0aem71YO5j5BjVkDf/Qog4R0O9PfpPZPZ3NeAABoOTc/7KceotHFElHmgcSk88tIHxGrhECezdRhLtmyKWttQpMStrxXCzCSYdyeY/K8Qyj9FVeZ3kmA4u/MAtLTmo7KdBhRFxPUPrEoMnhdlhP4/cnKaGbsLmeJ2vrKfMZuo38TlITaikhhDw245inKDyY1fPR/sGZZkRMUE34pIFW9hP8QbLE60EkDmnytkzF2Ejjtff6/LR8oH/0ekOk4xHebGg1l/OdixbYuQMvOq3jELtoKYx0yfsuwXDDNRH08wl+8bPJSAsIe8PJ9StdRAq7FVNQx4xSXCevYWFvFKwkIPSmbx6Yi6Ga9M3FQzhY9EG8ozOKtuunAlIHQhID9svIL92J30cd1RQh5898TAd0G1HLWO329R7W0YLphb3vrfeHT06WTd/XlpCLrroXM33vX+kK8GWdqQbQlYF/8g24HgHORYDS9vu2KeSlCSfpX6fc36lC7kR+COTQ13lX91PzmtqwC5FXM8ZWKJkX67nlSv1HRx5z4+67zbes4XQ5/QO8Xj5j0cCylchWlCT3FgedsCHbuC+XUQca4L3nuNGbccyx/Lrj/rIi"}
encryption_applied: 1
markup_language:
is_shared:
share_id:
conflict_original_id:
type_: 1

View File

@@ -0,0 +1 @@
{"version":3,"e2ee":true,"masterKeys":{"0e6c545903544ac1b08fe406d22155c2":{"id":"0e6c545903544ac1b08fe406d22155c2","checksum":"","encryption_method":4,"content":"{\"iv\":\"hkul4JTSj7dPhbNhmJVUgQ==\",\"v\":1,\"iter\":10000,\"ks\":256,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"bRAWx6CUYlU=\",\"ct\":\"owa8n48rN/J3wdQYnHa8VxdwHcNPNQELIVfm5uZMTQwVbFxiFfrN8b20Bc5V8esz1lF3VroQO6jNOChlEI3E5wI7B93q/L8j7OjOfcb1OFydNf3y4/wx8/3hgvDfG2ncpZMfWgOkQ5VFtfrlFPAsvWTBOAMSL6EY2asXxkSSZAONB0vP339cWaOkKgu7dRs8yyX9N/2wVw3KlwzlBGfjmZjemR6gBhmx4XK8edGlPXtg4mjnPhWfYZUOt5PYRwkp9OQOGSoAsnWBbt3WqOF4J/BGAn8TnWAGbuxJ+BV+8Bjn6+TJnu3SQjgo8rnHW78soyvcI8agEBV0jzGMXHK/P4IfTNdLq8Q1ylvRD8s5Iy2A0LzIjlismMAJddar+1yaGQapWnqsAeQaq7yiL5XN9SXJrjTQZihBGIMZ8TsuLsu9EXcSjtaQP1dCc8GxbQLUUrtyZB2LVzy4dQ3KBuRbf+4/jYYtrBDoP/LL4cQt7lX0Cprb9Ts8JXYf2bI0zHlaOmfagsGw4eIyiGYUDbNvcwl5JmfV0T4ICMeRt8J6jwvMfb9udsxkk/Cu6RCgJt27B38w1mD4PqsFSJkub/TLXOAV+ClR+OUCvOe+n33WfZONglrZwRMosjv1o5Y70K6TQGwFNADQHRiIwjLxa7O18RcR3a6uvRweyEeq0f7zLBWEhrrXJdvwnw==\"}","created_time":1624738094861,"updated_time":1624738094861,"source_application":"net.cozic.joplintest-cli"}},"activeMasterKeyId":"0e6c545903544ac1b08fe406d22155c2","updatedTime":1624738095090}

View File

@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1 @@
2020-07-16: In the new sync format, the version number is stored in /info.json. However, for backward compatibility, we need to keep the old version.txt file here, otherwise old clients will automatically recreate it, and assume a sync target version 1. So we keep it here but set its value to "2", so that old clients know that they need to be upgraded. This directory can be removed after a year or so, once we are confident that all clients have been upgraded to recent versions.

View File

@@ -0,0 +1,11 @@
id: 03a58517a48c408c93bc26c5b92a2b63
note_id: ceda4e635262419695e59a7c90aaffa6
tag_id: 5d37049a85ca469f97930acac11a9de5
created_time: 2021-06-26T20:08:08.364Z
updated_time: 2021-06-26T20:08:08.364Z
user_created_time: 2021-06-26T20:08:08.364Z
user_updated_time: 2021-06-26T20:08:08.364Z
encryption_cipher_text:
encryption_applied: 0
is_shared: 0
type_: 6

View File

@@ -0,0 +1,12 @@
tag2
id: 08341e97f8d14853a885d25f9ff020cb
created_time: 2021-06-26T20:08:08.370Z
updated_time: 2021-06-26T20:08:08.370Z
user_created_time: 2021-06-26T20:08:08.370Z
user_updated_time: 2021-06-26T20:08:08.370Z
encryption_cipher_text:
encryption_applied: 0
is_shared: 0
parent_id:
type_: 5

View File

@@ -0,0 +1,11 @@
id: 08e260b09d4d42fbb98b545a561d8f72
note_id: 264f9c3132f5473e9772c4872a083d2a
tag_id: 5d37049a85ca469f97930acac11a9de5
created_time: 2021-06-26T20:08:08.367Z
updated_time: 2021-06-26T20:08:08.367Z
user_created_time: 2021-06-26T20:08:08.367Z
user_updated_time: 2021-06-26T20:08:08.367Z
encryption_cipher_text:
encryption_applied: 0
is_shared: 0
type_: 6

View File

@@ -0,0 +1,11 @@
id: 12f2bd71f35e4ae6af168f3061bd8098
note_id: 264f9c3132f5473e9772c4872a083d2a
tag_id: 08341e97f8d14853a885d25f9ff020cb
created_time: 2021-06-26T20:08:08.371Z
updated_time: 2021-06-26T20:08:08.371Z
user_created_time: 2021-06-26T20:08:08.371Z
user_updated_time: 2021-06-26T20:08:08.371Z
encryption_cipher_text:
encryption_applied: 0
is_shared: 0
type_: 6

View File

@@ -0,0 +1,13 @@
folder1
id: 1754d54f708146119af2d1d97ba39191
created_time: 2021-06-26T20:08:08.240Z
updated_time: 2021-06-26T20:08:08.240Z
user_created_time: 2021-06-26T20:08:08.240Z
user_updated_time: 2021-06-26T20:08:08.240Z
encryption_cipher_text:
encryption_applied: 0
parent_id:
is_shared: 0
share_id:
type_: 2

View File

@@ -0,0 +1,28 @@
note3
id: 264f9c3132f5473e9772c4872a083d2a
parent_id: 1754d54f708146119af2d1d97ba39191
created_time: 2021-06-26T20:08:08.366Z
updated_time: 2021-06-26T20:08:08.366Z
is_conflict: 0
latitude: 0.00000000
longitude: 0.00000000
altitude: 0.0000
author:
source_url:
is_todo: 0
todo_due: 0
todo_completed: 0
source: joplin
source_application: net.cozic.joplintest-cli
application_data:
order: 1624738088366
user_created_time: 2021-06-26T20:08:08.366Z
user_updated_time: 2021-06-26T20:08:08.366Z
encryption_cipher_text:
encryption_applied: 0
markup_language: 1
is_shared: 0
share_id:
conflict_original_id:
type_: 1

View File

@@ -0,0 +1,28 @@
note4
id: 330f88a3d7bb4d5ebf488c92aa9115e0
parent_id: 1754d54f708146119af2d1d97ba39191
created_time: 2021-06-26T20:08:08.372Z
updated_time: 2021-06-26T20:08:08.372Z
is_conflict: 0
latitude: 0.00000000
longitude: 0.00000000
altitude: 0.0000
author:
source_url:
is_todo: 0
todo_due: 0
todo_completed: 0
source: joplin
source_application: net.cozic.joplintest-cli
application_data:
order: 1624738088372
user_created_time: 2021-06-26T20:08:08.372Z
user_updated_time: 2021-06-26T20:08:08.372Z
encryption_cipher_text:
encryption_applied: 0
markup_language: 1
is_shared: 0
share_id:
conflict_original_id:
type_: 1

View File

@@ -0,0 +1,12 @@
tag1
id: 5d37049a85ca469f97930acac11a9de5
created_time: 2021-06-26T20:08:08.362Z
updated_time: 2021-06-26T20:08:08.362Z
user_created_time: 2021-06-26T20:08:08.362Z
user_updated_time: 2021-06-26T20:08:08.362Z
encryption_cipher_text:
encryption_applied: 0
is_shared: 0
parent_id:
type_: 5

View File

@@ -0,0 +1,11 @@
id: 6cd49f1a6fac4861baa0e3240e134048
note_id: 330f88a3d7bb4d5ebf488c92aa9115e0
tag_id: 08341e97f8d14853a885d25f9ff020cb
created_time: 2021-06-26T20:08:08.374Z
updated_time: 2021-06-26T20:08:08.374Z
user_created_time: 2021-06-26T20:08:08.374Z
user_updated_time: 2021-06-26T20:08:08.374Z
encryption_cipher_text:
encryption_applied: 0
is_shared: 0
type_: 6

View File

@@ -0,0 +1,17 @@
photo.jpg
id: 91530b8c77b4451db32e706f4f365209
mime: image/jpeg
filename:
created_time: 2021-06-26T20:08:08.356Z
updated_time: 2021-06-26T20:08:08.356Z
user_created_time: 2021-06-26T20:08:08.356Z
user_updated_time: 2021-06-26T20:08:08.356Z
file_extension: jpg
encryption_cipher_text:
encryption_applied: 0
encryption_blob_encrypted: 0
size: 2720
is_shared: 0
share_id:
type_: 4

View File

@@ -0,0 +1,17 @@
photo.jpg
id: 9333a8289e1248cdaef3db6047de2fbd
mime: image/jpeg
filename:
created_time: 2021-06-26T20:08:08.479Z
updated_time: 2021-06-26T20:08:08.479Z
user_created_time: 2021-06-26T20:08:08.479Z
user_updated_time: 2021-06-26T20:08:08.479Z
file_extension: jpg
encryption_cipher_text:
encryption_applied: 0
encryption_blob_encrypted: 0
size: 2720
is_shared: 0
share_id:
type_: 4

View File

@@ -0,0 +1,13 @@
subFolder2
id: 9396bda49c0b447794639cb1069f9ca9
created_time: 2021-06-26T20:08:08.243Z
updated_time: 2021-06-26T20:08:08.243Z
user_created_time: 2021-06-26T20:08:08.243Z
user_updated_time: 2021-06-26T20:08:08.243Z
encryption_cipher_text:
encryption_applied: 0
parent_id: 1754d54f708146119af2d1d97ba39191
is_shared: 0
share_id:
type_: 2

View File

@@ -0,0 +1,13 @@
folder3
id: a23d3b2251854643aab04c0a592db4ba
created_time: 2021-06-26T20:08:08.376Z
updated_time: 2021-06-26T20:08:08.376Z
user_created_time: 2021-06-26T20:08:08.376Z
user_updated_time: 2021-06-26T20:08:08.376Z
encryption_cipher_text:
encryption_applied: 0
parent_id:
is_shared: 0
share_id:
type_: 2

View File

@@ -0,0 +1,11 @@
id: b9e8003b12c84826b733f688849443b5
note_id: dbdcb925536446be8474489092de8ce0
tag_id: 08341e97f8d14853a885d25f9ff020cb
created_time: 2021-06-26T20:08:08.483Z
updated_time: 2021-06-26T20:08:08.483Z
user_created_time: 2021-06-26T20:08:08.483Z
user_updated_time: 2021-06-26T20:08:08.483Z
encryption_cipher_text:
encryption_applied: 0
is_shared: 0
type_: 6

View File

@@ -0,0 +1,13 @@
folder2
id: bf054ce041ac4194ab2800f8495ae81f
created_time: 2021-06-26T20:08:08.375Z
updated_time: 2021-06-26T20:08:08.375Z
user_created_time: 2021-06-26T20:08:08.375Z
user_updated_time: 2021-06-26T20:08:08.375Z
encryption_cipher_text:
encryption_applied: 0
parent_id:
is_shared: 0
share_id:
type_: 2

View File

@@ -0,0 +1,30 @@
note1
![photo.jpg](:/91530b8c77b4451db32e706f4f365209)
id: ceda4e635262419695e59a7c90aaffa6
parent_id: 9396bda49c0b447794639cb1069f9ca9
created_time: 2021-06-26T20:08:08.244Z
updated_time: 2021-06-26T20:08:08.359Z
is_conflict: 0
latitude: 0.00000000
longitude: 0.00000000
altitude: 0.0000
author:
source_url:
is_todo: 0
todo_due: 0
todo_completed: 0
source: joplin
source_application: net.cozic.joplintest-cli
application_data:
order: 1624738088244
user_created_time: 2021-06-26T20:08:08.244Z
user_updated_time: 2021-06-26T20:08:08.359Z
encryption_cipher_text:
encryption_applied: 0
markup_language: 1
is_shared: 0
share_id:
conflict_original_id:
type_: 1

View File

@@ -0,0 +1,28 @@
note2
id: d00286f8d0354b28a02fea8a39accf96
parent_id: 9396bda49c0b447794639cb1069f9ca9
created_time: 2021-06-26T20:08:08.365Z
updated_time: 2021-06-26T20:08:08.365Z
is_conflict: 0
latitude: 0.00000000
longitude: 0.00000000
altitude: 0.0000
author:
source_url:
is_todo: 0
todo_due: 0
todo_completed: 0
source: joplin
source_application: net.cozic.joplintest-cli
application_data:
order: 1624738088365
user_created_time: 2021-06-26T20:08:08.365Z
user_updated_time: 2021-06-26T20:08:08.365Z
encryption_cipher_text:
encryption_applied: 0
markup_language: 1
is_shared: 0
share_id:
conflict_original_id:
type_: 1

View File

@@ -0,0 +1,30 @@
note5
![photo.jpg](:/9333a8289e1248cdaef3db6047de2fbd)
id: dbdcb925536446be8474489092de8ce0
parent_id: a23d3b2251854643aab04c0a592db4ba
created_time: 2021-06-26T20:08:08.377Z
updated_time: 2021-06-26T20:08:08.481Z
is_conflict: 0
latitude: 0.00000000
longitude: 0.00000000
altitude: 0.0000
author:
source_url:
is_todo: 0
todo_due: 0
todo_completed: 0
source: joplin
source_application: net.cozic.joplintest-cli
application_data:
order: 1624738088376
user_created_time: 2021-06-26T20:08:08.377Z
user_updated_time: 2021-06-26T20:08:08.481Z
encryption_cipher_text:
encryption_applied: 0
markup_language: 1
is_shared: 0
share_id:
conflict_original_id:
type_: 1

View File

@@ -0,0 +1,13 @@
subFolder1
id: e27847adda964cf696aedfcc049ee30f
created_time: 2021-06-26T20:08:08.242Z
updated_time: 2021-06-26T20:08:08.242Z
user_created_time: 2021-06-26T20:08:08.242Z
user_updated_time: 2021-06-26T20:08:08.242Z
encryption_cipher_text:
encryption_applied: 0
parent_id: 1754d54f708146119af2d1d97ba39191
is_shared: 0
share_id:
type_: 2

View File

@@ -0,0 +1 @@
{"version":3,"e2ee":false,"masterKeys":{},"activeMasterKeyId":"","updatedTime":1624738088713}

View File

@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@@ -14,6 +14,7 @@ const app = require('./app').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Resource = require('@joplin/lib/models/Resource').default;
const BaseItem = require('@joplin/lib/models/BaseItem').default;
const MasterKey = require('@joplin/lib/models/MasterKey').default;
const Note = require('@joplin/lib/models/Note').default;
const Tag = require('@joplin/lib/models/Tag').default;
const NoteTag = require('@joplin/lib/models/NoteTag').default;
@@ -69,7 +70,7 @@ BaseItem.loadClass('Folder', Folder);
BaseItem.loadClass('Resource', Resource);
BaseItem.loadClass('Tag', Tag);
BaseItem.loadClass('NoteTag', NoteTag);
// BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('Revision', Revision);
Setting.setConstant('appId', `net.cozic.joplin${bridge().env() === 'dev' ? 'dev' : ''}-desktop`);

View File

@@ -457,7 +457,7 @@ async function initialize(dispatch: Function) {
BaseItem.loadClass('Resource', Resource);
BaseItem.loadClass('Tag', Tag);
BaseItem.loadClass('NoteTag', NoteTag);
// BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('Revision', Revision);
const fsDriver = new FsDriverRN();

View File

@@ -12,7 +12,10 @@ const script: MigrationScript = {
for (const mk of masterKeys) masterKeyMap[mk.id] = mk;
const syncInfo: SyncTargetInfo = {
version: 2,
// When we first setup the local sync target info, we don't know
// what's on the remote one, so we set it to 0. During sync, the
// version from remote will be fetched.
version: 0,
e2ee: Setting.valueNoThrow('encryption.enabled', false),
masterKeys: masterKeyMap,
activeMasterKeyId: Setting.valueNoThrow('encryption.activeMasterKeyId', ''),

View File

@@ -10,7 +10,7 @@ import ItemChange from './ItemChange';
import ShareService from '../services/share/ShareService';
import itemCanBeEncrypted from './utils/itemCanBeEncrypted';
import { encryptionEnabled } from '../services/synchronizer/syncTargetInfoUtils';
const JoplinError = require('../JoplinError.js');
import JoplinError from '../JoplinError';
const { sprintf } = require('sprintf-js');
const moment = require('moment');
@@ -49,7 +49,7 @@ export default class BaseItem extends BaseModel {
{ type: BaseModel.TYPE_RESOURCE, className: 'Resource' },
{ type: BaseModel.TYPE_TAG, className: 'Tag' },
{ type: BaseModel.TYPE_NOTE_TAG, className: 'NoteTag' },
// { type: BaseModel.TYPE_MASTER_KEY, className: 'MasterKey' },
{ type: BaseModel.TYPE_MASTER_KEY, className: 'MasterKey' },
{ type: BaseModel.TYPE_REVISION, className: 'Revision' },
];
@@ -698,7 +698,7 @@ export default class BaseItem extends BaseModel {
const temp = this.syncItemClassNames();
const output = [];
for (let i = 0; i < temp.length; i++) {
// if (temp[i] === 'MasterKey') continue;
if (temp[i] === 'MasterKey') continue;
output.push(temp[i]);
}
return output;

View File

@@ -1,8 +1,7 @@
import MasterKey from '../models/MasterKey';
import Setting from '../models/Setting';
import { encryptionService, setupDatabaseAndSynchronizer, switchClient } from '../testing/test-utils';
import { setupDatabaseAndSynchronizer, switchClient } from '../testing/test-utils';
import MigrationService from './MigrationService';
import { setActiveMasterKeyId, setEncryptionEnabled, SyncTargetInfo } from './synchronizer/syncTargetInfoUtils';
import { SyncTargetInfo } from './synchronizer/syncTargetInfoUtils';
function migrationService() {
return new MigrationService();
@@ -15,23 +14,26 @@ describe('MigrationService', function() {
done();
});
it('should migrate to v40 - with keys', async () => {
const startTime = Date.now();
// Hard to test how it would migrate master keys since the code to save them
// to the database no longer exists.
const mk1 = await MasterKey.save(await encryptionService().generateMasterKey('1'));
const mk2 = await MasterKey.save(await encryptionService().generateMasterKey('2'));
setEncryptionEnabled(true);
setActiveMasterKeyId(mk2.id);
// it('should migrate to v40 - with keys', async () => {
// const startTime = Date.now();
await migrationService().runScript(40);
// const mk1 = await MasterKey.save(await encryptionService().generateMasterKey('1'));
// const mk2 = await MasterKey.save(await encryptionService().generateMasterKey('2'));
// Setting.setValue('encryption.enabled', true);
// Setting.setValue('encryption.activeMasterKeyId', mk1.id);
const info: SyncTargetInfo = JSON.parse(Setting.value('sync.info'));
expect(info.e2ee).toBe(true);
expect(info.activeMasterKeyId).toBe(mk2.id);
expect(info.version).toBe(2);
expect(Object.keys(info.masterKeys).sort()).toEqual([mk1.id, mk2.id].sort());
expect(info.updatedTime).toBeGreaterThanOrEqual(startTime);
});
// await migrationService().runScript(40, MasterKey.db());
// const info: SyncTargetInfo = JSON.parse(Setting.value('sync.info'));
// expect(info.e2ee).toBe(true);
// expect(info.activeMasterKeyId).toBe(mk1.id);
// expect(info.version).toBe(0);
// expect(Object.keys(info.masterKeys).sort()).toEqual([mk1.id, mk2.id].sort());
// expect(info.updatedTime).toBeGreaterThanOrEqual(startTime);
// });
it('should migrate to v40 - empty', async () => {
const startTime = Date.now();
@@ -41,7 +43,7 @@ describe('MigrationService', function() {
const info: SyncTargetInfo = JSON.parse(Setting.value('sync.info'));
expect(info.e2ee).toBe(false);
expect(info.activeMasterKeyId).toBe('');
expect(info.version).toBe(2);
expect(info.version).toBe(0);
expect(Object.keys(info.masterKeys)).toEqual([]);
expect(info.updatedTime).toBeGreaterThanOrEqual(startTime);
});

View File

@@ -0,0 +1,206 @@
// To create a sync target snapshot for the current syncVersion:
// - In test-utils, set syncTargetName_ to "filesystem"
// - Then run:
// node tests/support/createSyncTargetSnapshot.js normal && node tests/support/createSyncTargetSnapshot.js e2ee
//
// These tests work by a taking a sync target snapshot at a version n and upgrading it to n+1.
import LockHandler from './LockHandler';
import MigrationHandler from './MigrationHandler';
import { Dirnames } from './utils/types';
import { setSyncTargetName, fileApi, synchronizer, decryptionWorker, encryptionService, setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow, db } from '../../testing/test-utils';
import { deploySyncTargetSnapshot, testData, checkTestData } from '../../testing/syncTargetUtils';
import Setting from '../../models/Setting';
import MasterKey from '../../models/MasterKey';
import { loadMasterKeysFromSettings } from '../e2ee/utils';
import { remoteSyncTargetInfo } from './syncTargetInfoUtils';
const specTimeout = 60000 * 10; // Nextcloud tests can be slow
let lockHandler_: LockHandler = null;
let migrationHandler_: MigrationHandler = null;
function lockHandler(): LockHandler {
if (lockHandler_) return lockHandler_;
lockHandler_ = new LockHandler(fileApi());
return lockHandler_;
}
function migrationHandler(clientId: string = 'abcd'): MigrationHandler {
if (migrationHandler_) return migrationHandler_;
migrationHandler_ = new MigrationHandler(fileApi(), db(), lockHandler(), 'desktop', clientId);
return migrationHandler_;
}
interface MigrationTests {
[key: string]: Function;
}
const migrationTests: MigrationTests = {
2: async function() {
const items = (await fileApi().list('', { includeHidden: true })).items;
expect(items.filter((i: any) => i.path === '.resource' && i.isDir).length).toBe(1);
expect(items.filter((i: any) => i.path === 'locks' && i.isDir).length).toBe(1);
expect(items.filter((i: any) => i.path === 'temp' && i.isDir).length).toBe(1);
expect(items.filter((i: any) => i.path === 'info.json' && !i.isDir).length).toBe(1);
const versionForOldClients = await fileApi().get('.sync/version.txt');
expect(versionForOldClients).toBe('2');
},
3: async function() {
const items = (await fileApi().list('', { includeHidden: true })).items;
expect(items.filter((i: any) => i.path === '.resource' && i.isDir).length).toBe(1);
expect(items.filter((i: any) => i.path === 'locks' && i.isDir).length).toBe(1);
expect(items.filter((i: any) => i.path === 'temp' && i.isDir).length).toBe(1);
expect(items.filter((i: any) => i.path === 'info.json' && !i.isDir).length).toBe(1);
const versionForOldClients = await fileApi().get('.sync/version.txt');
expect(versionForOldClients).toBe('2');
},
};
const maxSyncVersion = Number(Object.keys(migrationTests).sort().pop());
async function testMigration(migrationVersion: number, maxSyncVersion: number) {
await deploySyncTargetSnapshot('normal', migrationVersion - 1);
const info = await remoteSyncTargetInfo(fileApi());
expect(info.version).toBe(migrationVersion - 1);
// Now, migrate to the new version
Setting.setConstant('syncVersion', migrationVersion);
await migrationHandler().upgrade(migrationVersion);
// Verify that it has been upgraded
const newInfo = await remoteSyncTargetInfo(fileApi());
expect(newInfo.version).toBe(migrationVersion);
await migrationTests[migrationVersion]();
if (migrationVersion !== maxSyncVersion) return;
// Now sync with that upgraded target
await synchronizer().start();
// Check that the data has not been altered
await expectNotThrow(async () => await checkTestData(testData));
// Check what happens if we switch to a different client and sync
await switchClient(2);
Setting.setConstant('syncVersion', migrationVersion);
await synchronizer().start();
await expectNotThrow(async () => await checkTestData(testData));
}
async function testMigrationE2EE(migrationVersion: number, maxSyncVersion: number) {
// First create some test data that will be used to validate
// that the migration didn't alter any data.
await deploySyncTargetSnapshot('e2ee', migrationVersion - 1);
// Now, migrate to the new version
Setting.setConstant('syncVersion', migrationVersion);
await migrationHandler().upgrade(migrationVersion);
// Verify that it has been upgraded
const newInfo = await remoteSyncTargetInfo(fileApi());
expect(newInfo.version).toBe(migrationVersion);
await migrationTests[migrationVersion]();
if (migrationVersion !== maxSyncVersion) return;
// Now sync with that upgraded target
await synchronizer().start();
// Decrypt the data
const masterKey = (await MasterKey.all())[0];
Setting.setObjectValue('encryption.passwordCache', masterKey.id, '123456');
await loadMasterKeysFromSettings(encryptionService());
await decryptionWorker().start();
// Check that the data has not been altered
await expectNotThrow(async () => await checkTestData(testData));
// Check what happens if we switch to a different client and sync
await switchClient(2);
Setting.setConstant('syncVersion', migrationVersion);
await synchronizer().start();
// Should throw because data hasn't been decrypted yet
await expectThrow(async () => await checkTestData(testData));
// Enable E2EE and decrypt
Setting.setObjectValue('encryption.passwordCache', masterKey.id, '123456');
await loadMasterKeysFromSettings(encryptionService());
await decryptionWorker().start();
// Should not throw because data is decrypted
await expectNotThrow(async () => await checkTestData(testData));
}
let previousSyncTargetName: string = '';
describe('MigrationHandler', function() {
beforeEach(async (done: Function) => {
// Note that, for undocumented reasons, the timeout argument passed
// to `test()` (or `it()`) is ignored if it is higher than the
// global Jest timeout. So we need to set it globally.
//
// https://github.com/facebook/jest/issues/5055#issuecomment-513585906
jest.setTimeout(specTimeout);
// To test the migrations, we have to use the filesystem sync target
// because the sync target snapshots are plain files. Eventually
// it should be possible to copy a filesystem target to memory
// but for now that will do.
previousSyncTargetName = setSyncTargetName('filesystem');
lockHandler_ = null;
migrationHandler_ = null;
await setupDatabaseAndSynchronizer(1);
await setupDatabaseAndSynchronizer(2);
await switchClient(1);
done();
});
afterEach(async (done: Function) => {
setSyncTargetName(previousSyncTargetName);
done();
});
it('should init a new sync target', (async () => {
// Check that basic folders "locks" and "temp" are created for new sync targets.
await migrationHandler().upgrade(1);
const result = await fileApi().list();
expect(result.items.filter((i: any) => i.path === Dirnames.Locks).length).toBe(1);
expect(result.items.filter((i: any) => i.path === Dirnames.Temp).length).toBe(1);
}), specTimeout);
it('should not allow syncing if the sync target is out-dated', (async () => {
await synchronizer().start();
await fileApi().put('info.json', `{"version":${Setting.value('syncVersion') - 1}}`);
await expectThrow(async () => await migrationHandler().checkCanSync(), 'outdatedSyncTarget');
}), specTimeout);
it('should not allow syncing if the client is out-dated', (async () => {
await synchronizer().start();
await fileApi().put('info.json', `{"version":${Setting.value('syncVersion') + 1}}`);
await expectThrow(async () => await migrationHandler().checkCanSync(), 'outdatedClient');
}), specTimeout);
it('should apply migration 2 normal', async () => {
await testMigration(2, maxSyncVersion);
}, specTimeout);
it('should apply migration 2 E2EE', async () => {
await testMigrationE2EE(2, maxSyncVersion);
}, specTimeout);
it('should apply migration 3 normal', async () => {
await testMigration(3, maxSyncVersion);
}, specTimeout);
it('should apply migration 3 E2EE', async () => {
await testMigrationE2EE(3, maxSyncVersion);
}, specTimeout);
});

View File

@@ -16,7 +16,7 @@ export interface SyncTargetInfo {
}
function serializeSyncTargetInfo(info: SyncTargetInfo): string {
return JSON.stringify(info);
return JSON.stringify(info, null, '\t');
}
function unserializeSyncTargetInfo(info: string): SyncTargetInfo {

View File

@@ -1,176 +0,0 @@
import LockHandler from '../../services/synchronizer/LockHandler';
import MigrationHandler from '../../services/synchronizer/MigrationHandler';
import { Dirnames } from '../../services/synchronizer/utils/types';
// To create a sync target snapshot for the current syncVersion:
// - In test-utils, set syncTargetName_ to "filesystem"
// - Then run:
// gulp buildTests -L && node tests-build/support/createSyncTargetSnapshot.js normal && node tests-build/support/createSyncTargetSnapshot.js e2ee
import { setSyncTargetName, fileApi, synchronizer, decryptionWorker, encryptionService, setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow, db } from '../../testing/test-utils';
import { deploySyncTargetSnapshot, testData, checkTestData } from '../../testing/syncTargetUtils';
import Setting from '../../models/Setting';
import MasterKey from '../../models/MasterKey';
import { loadMasterKeysFromSettings } from '../e2ee/utils';
import { remoteSyncTargetInfo } from './syncTargetInfoUtils';
const specTimeout = 60000 * 10; // Nextcloud tests can be slow
let lockHandler_: LockHandler = null;
let migrationHandler_: MigrationHandler = null;
function lockHandler(): LockHandler {
if (lockHandler_) return lockHandler_;
lockHandler_ = new LockHandler(fileApi());
return lockHandler_;
}
function migrationHandler(clientId: string = 'abcd'): MigrationHandler {
if (migrationHandler_) return migrationHandler_;
migrationHandler_ = new MigrationHandler(fileApi(), db(), lockHandler(), 'desktop', clientId);
return migrationHandler_;
}
interface MigrationTests {
[key: string]: Function;
}
const migrationTests: MigrationTests = {
2: async function() {
const items = (await fileApi().list('', { includeHidden: true })).items;
expect(items.filter((i: any) => i.path === '.resource' && i.isDir).length).toBe(1);
expect(items.filter((i: any) => i.path === 'locks' && i.isDir).length).toBe(1);
expect(items.filter((i: any) => i.path === 'temp' && i.isDir).length).toBe(1);
expect(items.filter((i: any) => i.path === 'info.json' && !i.isDir).length).toBe(1);
const versionForOldClients = await fileApi().get('.sync/version.txt');
expect(versionForOldClients).toBe('2');
},
};
let previousSyncTargetName: string = '';
describe('synchronizer_MigrationHandler', function() {
beforeEach(async (done: Function) => {
// Note that, for undocumented reasons, the timeout argument passed
// to `test()` (or `it()`) is ignored if it is higher than the
// global Jest timeout. So we need to set it globally.
//
// https://github.com/facebook/jest/issues/5055#issuecomment-513585906
jest.setTimeout(specTimeout);
// To test the migrations, we have to use the filesystem sync target
// because the sync target snapshots are plain files. Eventually
// it should be possible to copy a filesystem target to memory
// but for now that will do.
previousSyncTargetName = setSyncTargetName('filesystem');
lockHandler_ = null;
migrationHandler_ = null;
await setupDatabaseAndSynchronizer(1);
await setupDatabaseAndSynchronizer(2);
await switchClient(1);
done();
});
afterEach(async (done: Function) => {
setSyncTargetName(previousSyncTargetName);
done();
});
it('should init a new sync target', (async () => {
// Check that basic folders "locks" and "temp" are created for new sync targets.
await migrationHandler().upgrade(1);
const result = await fileApi().list();
expect(result.items.filter((i: any) => i.path === Dirnames.Locks).length).toBe(1);
expect(result.items.filter((i: any) => i.path === Dirnames.Temp).length).toBe(1);
}), specTimeout);
it('should not allow syncing if the sync target is out-dated', (async () => {
await synchronizer().start();
await fileApi().put('info.json', `{"version":${Setting.value('syncVersion') - 1}}`);
await expectThrow(async () => await migrationHandler().checkCanSync(), 'outdatedSyncTarget');
}), specTimeout);
it('should not allow syncing if the client is out-dated', (async () => {
await synchronizer().start();
await fileApi().put('info.json', `{"version":${Setting.value('syncVersion') + 1}}`);
await expectThrow(async () => await migrationHandler().checkCanSync(), 'outdatedClient');
}), specTimeout);
for (const migrationVersionString in migrationTests) {
const migrationVersion = Number(migrationVersionString);
it(`should migrate (${migrationVersion})`, (async () => {
await deploySyncTargetSnapshot('normal', migrationVersion - 1);
const info = await remoteSyncTargetInfo(fileApi());
expect(info.version).toBe(migrationVersion - 1);
// Now, migrate to the new version
await migrationHandler().upgrade(migrationVersion);
// Verify that it has been upgraded
const newInfo = await remoteSyncTargetInfo(fileApi());
expect(newInfo.version).toBe(migrationVersion);
await migrationTests[migrationVersion]();
// Now sync with that upgraded target
await synchronizer().start();
// Check that the data has not been altered
await expectNotThrow(async () => await checkTestData(testData));
// Check what happens if we switch to a different client and sync
await switchClient(2);
Setting.setConstant('syncVersion', migrationVersion);
await synchronizer().start();
await expectNotThrow(async () => await checkTestData(testData));
}), specTimeout);
it(`should migrate (E2EE) (${migrationVersion})`, (async () => {
// First create some test data that will be used to validate
// that the migration didn't alter any data.
await deploySyncTargetSnapshot('e2ee', migrationVersion - 1);
// Now, migrate to the new version
Setting.setConstant('syncVersion', migrationVersion);
await migrationHandler().upgrade(migrationVersion);
// Verify that it has been upgraded
const newInfo = await remoteSyncTargetInfo(fileApi());
expect(newInfo.version).toBe(migrationVersion);
await migrationTests[migrationVersion]();
// Now sync with that upgraded target
await synchronizer().start();
// Decrypt the data
const masterKey = (await MasterKey.all())[0];
Setting.setObjectValue('encryption.passwordCache', masterKey.id, '123456');
await loadMasterKeysFromSettings(encryptionService());
await decryptionWorker().start();
// Check that the data has not been altered
await expectNotThrow(async () => await checkTestData(testData));
// Check what happens if we switch to a different client and sync
await switchClient(2);
Setting.setConstant('syncVersion', migrationVersion);
await synchronizer().start();
// Should throw because data hasn't been decrypted yet
await expectThrow(async () => await checkTestData(testData));
// Enable E2EE and decrypt
Setting.setObjectValue('encryption.passwordCache', masterKey.id, '123456');
await loadMasterKeysFromSettings(encryptionService());
await decryptionWorker().start();
// Should not throw because data is decrypted
await expectNotThrow(async () => await checkTestData(testData));
}), specTimeout);
}
});

View File

@@ -1,4 +1,4 @@
import { syncDir, synchronizer, supportDir, loadEncryptionMasterKey, setupDatabaseAndSynchronizer, switchClient } from '../testing/test-utils';
import { syncDir, synchronizer, supportDir, loadEncryptionMasterKey, setupDatabaseAndSynchronizer, switchClient, synchronizerStart } from '../testing/test-utils';
import Setting from '../models/Setting';
import Folder from '../models/Folder';
import Note from '../models/Note';
@@ -8,6 +8,8 @@ import markdownUtils from '../markdownUtils';
import shim from '../shim';
import * as fs from 'fs-extra';
import { setEncryptionEnabled } from '../services/synchronizer/syncTargetInfoUtils';
const { shimInit } = require('../shim-init-node');
const sharp = require('sharp');
const snapshotBaseDir = `${supportDir}/syncTargetSnapshots`;
@@ -106,6 +108,8 @@ export async function deploySyncTargetSnapshot(syncTargetType: string, syncVersi
}
export async function main(syncTargetType: string) {
shimInit(sharp);
const validSyncTargetTypes = ['normal', 'e2ee'];
if (!validSyncTargetTypes.includes(syncTargetType)) throw new Error(`Sync target type must be: ${validSyncTargetTypes.join(', ')}`);
@@ -118,6 +122,8 @@ export async function main(syncTargetType: string) {
await loadEncryptionMasterKey();
}
await synchronizerStart();
await synchronizer().start();
if (!Setting.value('syncVersion')) throw new Error('syncVersion is not set');

View File

@@ -138,6 +138,7 @@ function setSyncTargetName(name: string) {
}
setSyncTargetName('memory');
// setSyncTargetName('filesystem');
// setSyncTargetName('nextcloud');
// setSyncTargetName('dropbox');
// setSyncTargetName('onedrive');
@@ -153,7 +154,7 @@ const syncDir = `${oldTestDir}/sync/${suiteName_}`;
// anyway.
let defaultJestTimeout = 90 * 1000;
if (isNetworkSyncTarget_) defaultJestTimeout = 60 * 1000 * 10;
jest.setTimeout(defaultJestTimeout);
if (typeof jest !== 'undefined') jest.setTimeout(defaultJestTimeout);
const dbLogger = new Logger();
dbLogger.addTarget(TargetType.Console);
@@ -170,7 +171,7 @@ BaseItem.loadClass('Folder', Folder);
BaseItem.loadClass('Resource', Resource);
BaseItem.loadClass('Tag', Tag);
BaseItem.loadClass('NoteTag', NoteTag);
// BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('Revision', Revision);
Setting.setConstant('appId', 'net.cozic.joplintest-cli');

View File

@@ -24,6 +24,7 @@ import { themeStyle } from '@joplin/lib/theme';
import Setting from '@joplin/lib/models/Setting';
import { Models } from '../models/factory';
import MustacheService from '../services/MustacheService';
import MasterKey from '@joplin/lib/models/MasterKey';
// const logger = Logger.create('JoplinUtils');
@@ -77,7 +78,7 @@ export async function initializeJoplinUtils(config: Config, models: Models, must
BaseItem.loadClass('Resource', Resource);
BaseItem.loadClass('Tag', Tag);
BaseItem.loadClass('NoteTag', NoteTag);
// BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('Revision', Revision);
// mustache_ = new MustacheService(config.viewDir, config.baseUrl);