@secrecy/lib 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/LICENSE +1 -1
  2. package/dist/lib/base-client.js +91 -0
  3. package/dist/lib/cache.js +4 -0
  4. package/dist/lib/client/SecrecryCareClient.js +19 -0
  5. package/dist/lib/client/SecrecyAppClient.js +87 -0
  6. package/dist/lib/client/SecrecyCloudClient.js +475 -0
  7. package/dist/lib/client/SecrecyDbClient.js +10 -0
  8. package/dist/lib/client/SecrecyMailClient.js +283 -0
  9. package/dist/lib/client/SecrecyPayClient.js +34 -0
  10. package/dist/lib/client/SecrecyUserClient.js +27 -0
  11. package/dist/lib/client/SecrecyWalletClient.js +50 -0
  12. package/dist/lib/client/convert/file.js +29 -0
  13. package/dist/lib/client/convert/mail.js +42 -0
  14. package/dist/lib/client/convert/node.js +100 -0
  15. package/dist/lib/client/helpers.js +103 -0
  16. package/dist/lib/client/index.js +49 -0
  17. package/dist/lib/client/storage.js +7 -0
  18. package/dist/lib/client/types/app.js +1 -0
  19. package/dist/lib/client/types/file.js +1 -0
  20. package/dist/lib/client/types/index.js +15 -0
  21. package/dist/lib/client/types/mail.js +1 -0
  22. package/dist/lib/client/types/node.js +1 -0
  23. package/dist/lib/client/types/user.js +1 -0
  24. package/dist/lib/client.js +47 -0
  25. package/dist/lib/crypto/file.js +184 -0
  26. package/dist/lib/crypto/index.js +41 -0
  27. package/dist/lib/error/client.js +10 -0
  28. package/dist/lib/error/index.js +10 -0
  29. package/dist/lib/error/server.js +27 -0
  30. package/dist/lib/index.js +10 -0
  31. package/dist/lib/minify/index.js +23 -0
  32. package/dist/lib/minify/lz4.js +517 -0
  33. package/dist/lib/sodium.js +5 -0
  34. package/dist/lib/types.js +1 -0
  35. package/dist/lib/utils/array.js +25 -0
  36. package/dist/lib/utils/base64.js +2 -0
  37. package/dist/lib/utils/popup-tools.js +180 -0
  38. package/dist/lib/utils/promise.js +20 -0
  39. package/dist/lib/utils/store-buddy.js +60 -0
  40. package/dist/lib/utils/time.js +13 -0
  41. package/dist/lib/worker/md5.js +18 -0
  42. package/dist/lib/worker/sodium.js +95 -0
  43. package/dist/lib/worker/workerCodes.js +254 -0
  44. package/dist/types/base-client.d.ts +28 -0
  45. package/dist/types/cache.d.ts +11 -0
  46. package/dist/types/client/SecrecryCareClient.d.ts +9 -0
  47. package/dist/types/client/SecrecyAppClient.d.ts +20 -0
  48. package/dist/types/client/SecrecyCloudClient.d.ts +88 -0
  49. package/dist/types/client/SecrecyDbClient.d.ts +7 -0
  50. package/dist/types/client/SecrecyMailClient.d.ts +42 -0
  51. package/dist/types/client/SecrecyPayClient.d.ts +27 -0
  52. package/dist/types/client/SecrecyUserClient.d.ts +14 -0
  53. package/dist/{client → types/client}/SecrecyWalletClient.d.ts +9 -12
  54. package/dist/types/client/convert/file.d.ts +4 -0
  55. package/dist/types/client/convert/mail.d.ts +8 -0
  56. package/dist/types/client/convert/node.d.ts +7 -0
  57. package/dist/types/client/helpers.d.ts +26 -0
  58. package/dist/types/client/index.d.ts +29 -0
  59. package/dist/{client → types/client}/storage.d.ts +2 -2
  60. package/dist/types/client/types/app.d.ts +2 -0
  61. package/dist/types/client/types/file.d.ts +6 -0
  62. package/dist/types/client/types/index.d.ts +46 -0
  63. package/dist/types/client/types/mail.d.ts +87 -0
  64. package/dist/{client/types/Node.d.ts → types/client/types/node.d.ts} +20 -25
  65. package/dist/types/client/types/user.d.ts +3 -0
  66. package/dist/types/client.d.ts +12138 -0
  67. package/dist/{crypto → types/crypto}/file.d.ts +4 -4
  68. package/dist/{crypto → types/crypto}/index.d.ts +1 -4
  69. package/dist/types/error/client.d.ts +22 -0
  70. package/dist/types/error/index.d.ts +40 -0
  71. package/dist/types/error/server.d.ts +26 -0
  72. package/dist/types/index.d.ts +13 -0
  73. package/dist/{minify → types/minify}/index.d.ts +1 -1
  74. package/dist/types/minify/lz4.d.ts +35 -0
  75. package/dist/{sodium.d.ts → types/sodium.d.ts} +1 -1
  76. package/dist/types/types.d.ts +10 -0
  77. package/dist/{utils/utils.d.ts → types/utils/array.d.ts} +0 -1
  78. package/dist/types/utils/base64.d.ts +1 -0
  79. package/dist/types/utils/popup-tools.d.ts +52 -0
  80. package/dist/types/utils/promise.d.ts +1 -0
  81. package/dist/types/utils/store-buddy.d.ts +130 -0
  82. package/dist/{worker → types/worker}/sodium.d.ts +1 -1
  83. package/package.json +48 -73
  84. package/dist/BaseClient.d.ts +0 -111
  85. package/dist/BaseClient.js +0 -506
  86. package/dist/PopupTools.d.ts +0 -17
  87. package/dist/PopupTools.js +0 -195
  88. package/dist/ZeusThunder.d.ts +0 -2
  89. package/dist/ZeusThunder.js +0 -65
  90. package/dist/cache.d.ts +0 -6
  91. package/dist/cache.js +0 -4
  92. package/dist/client/SecrecyAppClient.d.ts +0 -17
  93. package/dist/client/SecrecyAppClient.js +0 -226
  94. package/dist/client/SecrecyCloudClient.d.ts +0 -89
  95. package/dist/client/SecrecyCloudClient.js +0 -1405
  96. package/dist/client/SecrecyDbClient.d.ts +0 -48
  97. package/dist/client/SecrecyDbClient.js +0 -419
  98. package/dist/client/SecrecyMailClient.d.ts +0 -42
  99. package/dist/client/SecrecyMailClient.js +0 -1022
  100. package/dist/client/SecrecyPayClient.d.ts +0 -28
  101. package/dist/client/SecrecyPayClient.js +0 -68
  102. package/dist/client/SecrecyWalletClient.js +0 -73
  103. package/dist/client/convert/file.d.ts +0 -5
  104. package/dist/client/convert/file.js +0 -33
  105. package/dist/client/convert/mail.d.ts +0 -3
  106. package/dist/client/convert/mail.js +0 -42
  107. package/dist/client/convert/node.d.ts +0 -9
  108. package/dist/client/convert/node.js +0 -87
  109. package/dist/client/helpers.d.ts +0 -28
  110. package/dist/client/helpers.js +0 -119
  111. package/dist/client/index.d.ts +0 -34
  112. package/dist/client/index.js +0 -46
  113. package/dist/client/storage.js +0 -12
  114. package/dist/client/types/File.d.ts +0 -14
  115. package/dist/client/types/File.js +0 -3
  116. package/dist/client/types/Inputs.d.ts +0 -16
  117. package/dist/client/types/Inputs.js +0 -3
  118. package/dist/client/types/Node.js +0 -3
  119. package/dist/client/types/UserAppNotifications.d.ts +0 -6
  120. package/dist/client/types/UserAppNotifications.js +0 -3
  121. package/dist/client/types/UserAppSettings.d.ts +0 -5
  122. package/dist/client/types/UserAppSettings.js +0 -3
  123. package/dist/client/types/index.d.ts +0 -120
  124. package/dist/client/types/index.js +0 -8
  125. package/dist/client/types/selectors.d.ts +0 -400
  126. package/dist/client/types/selectors.js +0 -135
  127. package/dist/crypto/file.js +0 -195
  128. package/dist/crypto/index.js +0 -45
  129. package/dist/error.d.ts +0 -33
  130. package/dist/error.js +0 -3
  131. package/dist/index.d.ts +0 -14
  132. package/dist/index.js +0 -10
  133. package/dist/minify/index.js +0 -23
  134. package/dist/minify/lz4.d.ts +0 -5
  135. package/dist/minify/lz4.js +0 -539
  136. package/dist/sodium.js +0 -6
  137. package/dist/utils/encoders.d.ts +0 -26
  138. package/dist/utils/encoders.js +0 -18
  139. package/dist/utils/store-buddy.d.ts +0 -14
  140. package/dist/utils/store-buddy.js +0 -58
  141. package/dist/utils/time.js +0 -12
  142. package/dist/utils/utils.js +0 -47
  143. package/dist/worker/md5.js +0 -24
  144. package/dist/worker/sodium.js +0 -118
  145. package/dist/worker/workerCodes.js +0 -255
  146. package/dist/zeus/const.d.ts +0 -7
  147. package/dist/zeus/const.js +0 -1846
  148. package/dist/zeus/index.d.ts +0 -8721
  149. package/dist/zeus/index.js +0 -642
  150. /package/dist/{utils → types/utils}/time.d.ts +0 -0
  151. /package/dist/{worker → types/worker}/md5.d.ts +0 -0
  152. /package/dist/{worker → types/worker}/workerCodes.d.ts +0 -0
@@ -0,0 +1,10 @@
1
+ export class SecrecyDbClient {
2
+ // #client: SecrecyClient;
3
+ // #keys: KeyPair;
4
+ #apiClient;
5
+ constructor(_client, _keys, apiClient) {
6
+ // this.#client = client;
7
+ // this.#keys = keys;
8
+ this.#apiClient = apiClient;
9
+ }
10
+ }
@@ -0,0 +1,283 @@
1
+ import { filesCache } from '../cache.js';
2
+ import { encryptCryptoBox, sodium } from '../index.js';
3
+ import { convertInternalMailToExternal } from './convert/mail.js';
4
+ export class SecrecyMailClient {
5
+ #client;
6
+ #keys;
7
+ #apiClient;
8
+ constructor(client, keys, apiClient) {
9
+ this.#client = client;
10
+ this.#keys = keys;
11
+ this.#apiClient = apiClient;
12
+ }
13
+ async get({ id }) {
14
+ const mail = await this.#apiClient.mail.byId.query({ id });
15
+ return await convertInternalMailToExternal({
16
+ mail,
17
+ client: this.#client,
18
+ keyPair: this.#keys,
19
+ });
20
+ }
21
+ async recover({ mailId }) {
22
+ const { isRecovered } = await this.#apiClient.mail.recover.mutate({
23
+ id: mailId,
24
+ });
25
+ return isRecovered;
26
+ }
27
+ async deletedMails({ mailType, }) {
28
+ const deletedMails = await this.#apiClient.mail.deleted.query({
29
+ type: mailType,
30
+ });
31
+ return await Promise.all(deletedMails.map(async (mail) => await convertInternalMailToExternal({
32
+ mail,
33
+ client: this.#client,
34
+ keyPair: this.#keys,
35
+ })));
36
+ }
37
+ async create(data, customMessage) {
38
+ const mail = await this.createDraft(data);
39
+ return await this.sendDraft(mail.mailIntegrityId, customMessage);
40
+ }
41
+ async waitingReceivedMails() {
42
+ // TODO
43
+ // const waitingReceivedMails =
44
+ // await this.#apiClient.mail.waitingReceived.query({})
45
+ // const result = waitingReceivedMails.map((m) => ({
46
+ // id: Math.random().toString(36).substr(2, 9),
47
+ // ...m,
48
+ // }))
49
+ // return result
50
+ return [];
51
+ }
52
+ async updateDraft(draftId, { body, subject, senderFiles, recipients, replyToId }) {
53
+ const drafts = await this.draftMails();
54
+ const draft = drafts.find((d) => d.mailIntegrityId === draftId);
55
+ if (draft === undefined) {
56
+ throw new Error(`Invalid draft ${draftId}`);
57
+ }
58
+ let hashKey = null;
59
+ let hash = null;
60
+ if (body !== undefined || subject !== undefined) {
61
+ hashKey = sodium.randombytes_buf(sodium.crypto_generichash_KEYBYTES, 'hex');
62
+ hash = sodium.crypto_generichash(sodium.crypto_generichash_BYTES, JSON.stringify({ body, subject }), hashKey, 'hex');
63
+ }
64
+ if (senderFiles !== undefined) {
65
+ for (const f of senderFiles) {
66
+ let file = filesCache.get(f.id);
67
+ if (file === undefined) {
68
+ await this.#client.cloud.fileMetadata({ id: f.id });
69
+ file = filesCache.get(f.id);
70
+ if (file === undefined) {
71
+ throw new Error(`File ${f.name} (${f.id}) does not exists`);
72
+ }
73
+ }
74
+ f.name = sodium.to_hex(encryptCryptoBox(sodium.from_string(f.name), this.#keys.publicKey, this.#keys.privateKey));
75
+ }
76
+ }
77
+ const updateDraftMail = await this.#apiClient.mail.updateDraft.mutate({
78
+ id: draftId,
79
+ recipients: recipients ?? null,
80
+ replyToId: replyToId ?? null,
81
+ body: body !== undefined
82
+ ? sodium.to_hex(encryptCryptoBox(sodium.from_string(body), this.#keys.publicKey, this.#keys.privateKey))
83
+ : null,
84
+ subject: subject !== undefined
85
+ ? sodium.to_hex(encryptCryptoBox(sodium.from_string(subject), this.#keys.publicKey, this.#keys.privateKey))
86
+ : null,
87
+ senderFiles: senderFiles ?? null,
88
+ hash,
89
+ hashKey,
90
+ });
91
+ return (await convertInternalMailToExternal({
92
+ mail: updateDraftMail,
93
+ client: this.#client,
94
+ keyPair: this.#keys,
95
+ }));
96
+ }
97
+ async deleteDraft(draftId) {
98
+ const { isDeleted } = await this.#apiClient.mail.deleteDraft.mutate({
99
+ id: draftId,
100
+ });
101
+ return isDeleted;
102
+ }
103
+ async deleteTrash({ ids }) {
104
+ const { isDeleted } = await this.#apiClient.mail.deleteTrash.mutate({
105
+ ids,
106
+ });
107
+ return isDeleted;
108
+ }
109
+ async emptyTrash() {
110
+ const { isDeleted } = await this.#apiClient.mail.emptyTrash.mutate({});
111
+ return isDeleted;
112
+ }
113
+ async delete({ mailId }) {
114
+ const { isDeleted } = await this.#apiClient.mail.delete.mutate({
115
+ id: mailId,
116
+ });
117
+ return isDeleted;
118
+ }
119
+ async sendDraft(draftId, customMessage) {
120
+ const drafts = await this.draftMails();
121
+ const draft = drafts.find((d) => d.mailIntegrityId === draftId);
122
+ if (draft === undefined) {
123
+ return false;
124
+ }
125
+ const temporaryRecipients = new Array();
126
+ const recipients = new Array(); // TODO
127
+ for (const { email } of draft.temporaryRecipients) {
128
+ if (email === undefined) {
129
+ continue;
130
+ }
131
+ const input = await this._eachUser(draft.files, draft.subject, draft.body, email);
132
+ if (input === null) {
133
+ temporaryRecipients.push(email);
134
+ }
135
+ else {
136
+ recipients.push(input);
137
+ }
138
+ }
139
+ for (const { id } of draft.recipients) {
140
+ const input = await this._eachUser(draft.files, draft.subject, draft.body, id);
141
+ if (input === null) {
142
+ temporaryRecipients.push(id);
143
+ }
144
+ else {
145
+ recipients.push(input);
146
+ }
147
+ }
148
+ const { isSent } = await this.#apiClient.mail.sendDraft.mutate({
149
+ temporaryRecipients,
150
+ recipients,
151
+ id: draft.mailIntegrityId,
152
+ customMessage: customMessage ?? null,
153
+ });
154
+ return isSent;
155
+ }
156
+ async sendWaitingEmails() {
157
+ // TODO opti this
158
+ const mails = await this.sentMails();
159
+ const filtered = mails.filter((m) => m.temporaryRecipients.length > 0);
160
+ for (const mail of filtered) {
161
+ for (const { email } of mail.temporaryRecipients) {
162
+ if (email === undefined) {
163
+ continue;
164
+ }
165
+ try {
166
+ const input = await this._eachUser(mail.files, mail.subject, mail.body, email);
167
+ if (input === null) {
168
+ continue;
169
+ }
170
+ await this.#apiClient.mail.sendOne.mutate({
171
+ id: mail.mailIntegrityId,
172
+ recipient: input,
173
+ });
174
+ }
175
+ catch {
176
+ continue;
177
+ }
178
+ }
179
+ }
180
+ }
181
+ async createDraft({ body, subject, senderFiles, recipients, replyToId, }) {
182
+ const hashKey = sodium.randombytes_buf(sodium.crypto_generichash_KEYBYTES, 'hex');
183
+ const hash = sodium.crypto_generichash(sodium.crypto_generichash_BYTES, JSON.stringify({ body, subject }), hashKey, 'hex');
184
+ for (const f of senderFiles) {
185
+ let file = filesCache.get(f.id);
186
+ if (file === undefined) {
187
+ await this.#client.cloud.fileMetadata({ id: f.id });
188
+ file = filesCache.get(f.id);
189
+ if (file === undefined) {
190
+ throw new Error(`File ${f.name} (${f.id}) does not exists`);
191
+ }
192
+ }
193
+ senderFiles.push({
194
+ id: file.id,
195
+ name: sodium.to_hex(encryptCryptoBox(sodium.from_string(f.name), this.#keys.publicKey, this.#keys.privateKey)),
196
+ });
197
+ }
198
+ const createDraftMail = await this.#apiClient.mail.createDraft.mutate({
199
+ // recipients: recipientsIds,
200
+ recipients, // TODO
201
+ replyToId,
202
+ body: sodium.to_hex(encryptCryptoBox(sodium.from_string(body), this.#keys.publicKey, this.#keys.privateKey)),
203
+ subject: sodium.to_hex(encryptCryptoBox(sodium.from_string(subject), this.#keys.publicKey, this.#keys.privateKey)),
204
+ senderFiles,
205
+ hash,
206
+ hashKey,
207
+ });
208
+ return (await convertInternalMailToExternal({
209
+ mail: createDraftMail,
210
+ client: this.#client,
211
+ keyPair: this.#keys,
212
+ }));
213
+ }
214
+ async read({ mailId }) {
215
+ const { isRead } = await this.#apiClient.mail.read.mutate({
216
+ id: mailId,
217
+ });
218
+ return isRead;
219
+ }
220
+ async unread({ mailId }) {
221
+ const { isUnread } = await this.#apiClient.mail.unread.mutate({
222
+ id: mailId,
223
+ });
224
+ return isUnread;
225
+ }
226
+ async receivedMails() {
227
+ const receivedMails = await this.#apiClient.mail.received.query({});
228
+ return await Promise.all(receivedMails.map(async (mail) => (await convertInternalMailToExternal({
229
+ mail,
230
+ client: this.#client,
231
+ keyPair: this.#keys,
232
+ }))));
233
+ }
234
+ async sentMails() {
235
+ const sentMails = await this.#apiClient.mail.sent.query({});
236
+ return await Promise.all(sentMails.map(async (mail) => (await convertInternalMailToExternal({
237
+ mail,
238
+ client: this.#client,
239
+ keyPair: this.#keys,
240
+ }))));
241
+ }
242
+ async draftMails() {
243
+ const draftMails = await this.#apiClient.mail.draft.query({});
244
+ return await Promise.all(draftMails.map(async (mail) => (await convertInternalMailToExternal({
245
+ mail,
246
+ client: this.#client,
247
+ keyPair: this.#keys,
248
+ }))));
249
+ }
250
+ async unreadReceivedMailsCount() {
251
+ const unreadReceivedMailsCount = await this.#apiClient.mail.unreadReceivedCount.query({});
252
+ return unreadReceivedMailsCount;
253
+ }
254
+ _eachUser = async (files, subject, body, idOrMail) => {
255
+ // const pubKey = await this.#client.app.userPublicKey(userId)
256
+ const pubKey = await this.#client.app.userPublicKey(idOrMail);
257
+ // const recipientsFiles = new Array<MailFileInput>()
258
+ const recipientsFiles = new Array();
259
+ for (const f of files) {
260
+ let fileInHistory = filesCache.get(f.id);
261
+ if (fileInHistory === undefined) {
262
+ await this.#client.cloud.fileMetadata({ id: f.id });
263
+ fileInHistory = filesCache.get(f.id);
264
+ if (fileInHistory === undefined) {
265
+ throw new Error(`File ${f.name} (${f.id}) does not exists`);
266
+ }
267
+ }
268
+ const key = fileInHistory.key;
269
+ recipientsFiles.push({
270
+ id: f.id,
271
+ name: sodium.to_hex(encryptCryptoBox(sodium.from_string(f.name), pubKey, this.#keys.privateKey)),
272
+ fileKey: sodium.to_hex(encryptCryptoBox(sodium.from_hex(key), pubKey, this.#keys.privateKey)),
273
+ });
274
+ }
275
+ return {
276
+ // recipientId: userId,
277
+ recipientId: idOrMail,
278
+ body: sodium.to_hex(encryptCryptoBox(sodium.from_string(body), pubKey, this.#keys.privateKey)),
279
+ subject: sodium.to_hex(encryptCryptoBox(sodium.from_string(subject), pubKey, this.#keys.privateKey)),
280
+ files: recipientsFiles,
281
+ };
282
+ };
283
+ }
@@ -0,0 +1,34 @@
1
+ import { getUrl } from '../index.js';
2
+ import { popup } from '../utils/popup-tools.js';
3
+ export class SecrecyPayClient {
4
+ #client;
5
+ // #keys: KeyPair
6
+ // #apiClient: ApiClient
7
+ constructor(client, _keys, _apiClient) {
8
+ this.#client = client;
9
+ // this.#keys = keys
10
+ // this.#apiClient = apiClient
11
+ }
12
+ async confirmPaymentIntent({ paymentIntentId, secrecyIdWhoCreatedPaymentIntent, secrecyIdWhoNeedToConfirmPaymentIntent, amount, currency, }) {
13
+ const url = getUrl({
14
+ hash: Buffer.from(JSON.stringify({
15
+ appSession: this.#client.sessionId,
16
+ paymentIntentId,
17
+ secrecyIdWhoCreatedPaymentIntent,
18
+ secrecyIdWhoNeedToConfirmPaymentIntent,
19
+ amount,
20
+ currency,
21
+ })).toString('base64'),
22
+ path: '/account/iframe/pay-confirm',
23
+ });
24
+ return await new Promise((resolve, reject) => popup(url, 'Secrecy Pay - Confirm Payment Intent', {
25
+ width: 500,
26
+ }, (err, data) => {
27
+ if (err !== undefined) {
28
+ reject(err);
29
+ return;
30
+ }
31
+ resolve(data);
32
+ }));
33
+ }
34
+ }
@@ -0,0 +1,27 @@
1
+ export class SecrecyUserClient {
2
+ #apiClient;
3
+ constructor(_client, _keys, apiClient) {
4
+ this.#apiClient = apiClient;
5
+ }
6
+ async answerInvitation(input) {
7
+ return await this.#apiClient.contacts.answerInvitation.mutate(input);
8
+ }
9
+ async cancelInvitation(input) {
10
+ return await this.#apiClient.contacts.cancelInvitation.mutate(input);
11
+ }
12
+ async createInvitation(input) {
13
+ return await this.#apiClient.contacts.createInvitation.mutate(input);
14
+ }
15
+ async getContacts(input) {
16
+ return await this.#apiClient.contacts.getContacts.query(input);
17
+ }
18
+ async getReceivedInvitations(input) {
19
+ return await this.#apiClient.contacts.getReceivedInvitations.query(input);
20
+ }
21
+ async getSentInvitations(input) {
22
+ return await this.#apiClient.contacts.getSentInvitations.query(input);
23
+ }
24
+ async removeContact(input) {
25
+ return await this.#apiClient.contacts.removeContact.mutate(input);
26
+ }
27
+ }
@@ -0,0 +1,50 @@
1
+ import { getUrl } from '../index.js';
2
+ import { popup } from '../utils/popup-tools.js';
3
+ export class SecrecyWalletClient {
4
+ #client;
5
+ // #keys: KeyPair;
6
+ // #thunder: ReturnType<typeof Thunder>;
7
+ constructor(client) {
8
+ this.#client = client;
9
+ // this.#keys = keys;
10
+ // this.#thunder = thunder;
11
+ }
12
+ async createTransaction({ network = 'mainnet', tx, }) {
13
+ const url = getUrl({
14
+ hash: Buffer.from(JSON.stringify({
15
+ appSession: this.#client.sessionId,
16
+ network,
17
+ tx,
18
+ })).toString('base64'),
19
+ path: '/account/iframe/wallet-transaction',
20
+ });
21
+ return await new Promise((resolve, reject) => popup(url, 'Secrecy Wallet - Transaction', {
22
+ width: 500,
23
+ }, (err, data) => {
24
+ if (err !== undefined) {
25
+ reject(err);
26
+ return;
27
+ }
28
+ resolve(data);
29
+ }));
30
+ }
31
+ async createSignature({ network = 'mainnet', message, }) {
32
+ const url = getUrl({
33
+ hash: Buffer.from(JSON.stringify({
34
+ appSession: this.#client.sessionId,
35
+ network,
36
+ message,
37
+ })).toString('base64'),
38
+ path: '/account/iframe/wallet-signature',
39
+ });
40
+ return await new Promise((resolve, reject) => popup(url, 'Secrecy Wallet - Signature', {
41
+ width: 500,
42
+ }, (err, data) => {
43
+ if (err !== undefined) {
44
+ reject(err);
45
+ return;
46
+ }
47
+ resolve(data);
48
+ }));
49
+ }
50
+ }
@@ -0,0 +1,29 @@
1
+ import { filesCache } from '../../cache.js';
2
+ import { decryptCryptoBox } from '../../crypto/index.js';
3
+ import { sodium } from '../../sodium.js';
4
+ export function apiFileToInternal(apiFile, keyPair) {
5
+ const file = {
6
+ id: apiFile.id,
7
+ md5: apiFile.md5,
8
+ md5Encrypted: apiFile.md5Encrypted,
9
+ createdAt: apiFile.createdAt,
10
+ size: apiFile.size,
11
+ sizeBefore: apiFile.sizeBefore,
12
+ key: sodium.to_hex(decryptCryptoBox(sodium.from_hex(apiFile.access.key), apiFile.access.sharedByPubKey, keyPair.privateKey)),
13
+ };
14
+ filesCache.set(file.id, file);
15
+ return file;
16
+ }
17
+ export function internalFileToFile(internal) {
18
+ return {
19
+ id: internal.id,
20
+ md5: internal.md5,
21
+ md5Encrypted: internal.md5Encrypted,
22
+ createdAt: internal.createdAt,
23
+ size: internal.size,
24
+ sizeBefore: internal.sizeBefore,
25
+ };
26
+ }
27
+ export function apiFileToExternal(apiFile, keyPair) {
28
+ return internalFileToFile(apiFileToInternal(apiFile, keyPair));
29
+ }
@@ -0,0 +1,42 @@
1
+ import { sodium, decryptCryptoBox, } from '../../index.js';
2
+ export async function convertInternalMailToExternal({ client, mail, keyPair, }) {
3
+ let type = mail.type;
4
+ if (mail.mailIntegrityDraft !== null) {
5
+ type = 'draft';
6
+ }
7
+ const mI = type === 'draft' ? mail.mailIntegrityDraft : mail.mailIntegrity;
8
+ if (mI === null) {
9
+ throw new Error('Mail integrity is null');
10
+ }
11
+ const pubKey = mail.type === 'received'
12
+ ? await client.app.userPublicKey(mail.sender.id)
13
+ : keyPair.publicKey;
14
+ const privateKey = keyPair.privateKey;
15
+ const body = sodium.to_string(decryptCryptoBox(sodium.from_hex(mail.body), pubKey, privateKey));
16
+ const subject = sodium.to_string(decryptCryptoBox(sodium.from_hex(mail.subject), pubKey, privateKey));
17
+ const hash = sodium.crypto_generichash(sodium.crypto_generichash_BYTES, JSON.stringify({ body, subject }), mI.hashKey, 'hex');
18
+ return {
19
+ type,
20
+ id: mail.id,
21
+ mailIntegrityId: mI.id,
22
+ replyTo: mI.replyTo?.id,
23
+ body,
24
+ subject,
25
+ createdAt: mail.createdAt,
26
+ deletedAt: mail.deletedAt,
27
+ openedAt: mail.openedAt,
28
+ isAltered: hash !== mI.hash,
29
+ // temporaryRecipients: mI.temporaryRecipients,
30
+ temporaryRecipients: [], // TODO
31
+ recipients: mI.recipients,
32
+ sender: mail.sender,
33
+ files: mail.files.map((f) => {
34
+ const name = sodium.to_string(decryptCryptoBox(sodium.from_hex(f.filename), pubKey, privateKey));
35
+ return {
36
+ id: f.fileId,
37
+ name,
38
+ key: f.fileKey,
39
+ };
40
+ }),
41
+ };
42
+ }
@@ -0,0 +1,100 @@
1
+ import { sodium } from '../../sodium.js';
2
+ import { decryptCryptoBox } from '../../crypto/index.js';
3
+ import { nodesCache } from '../../cache.js';
4
+ import { decryptSecretstream } from '../../crypto/file.js';
5
+ import { apiFileToInternal, internalFileToFile } from './file.js';
6
+ export async function apiNodeToInternal(apiNode, keyPair) {
7
+ const internal = {
8
+ id: apiNode.id,
9
+ type: apiNode.type,
10
+ access: apiNode.access,
11
+ name: apiNode.name,
12
+ isFavorite: apiNode.isFavorite,
13
+ // TODO
14
+ // breadcrumb: apiNode.breadcrumb,
15
+ // createdBy: apiNode.createdBy.user,
16
+ breadcrumb: [],
17
+ createdBy: {
18
+ firstname: apiNode.createdBy.userId,
19
+ lastname: apiNode.createdBy.userId,
20
+ avatar: apiNode.createdBy.userId,
21
+ id: apiNode.createdBy.userId,
22
+ isSearchable: true,
23
+ },
24
+ currentFileId: null,
25
+ // currentFileId: apiNode.currentFileId ?? null,
26
+ sizes: {
27
+ // size: apiNode.sizes.size,
28
+ // sizeBefore: apiNode.sizes.sizeBefore,
29
+ size: 0n,
30
+ sizeBefore: 0n,
31
+ },
32
+ createdAt: apiNode.createdAt,
33
+ updatedAt: apiNode.updatedAt,
34
+ deletedAt: apiNode.deletedAt,
35
+ users: apiNode.users,
36
+ parentId: apiNode.parentId ?? null,
37
+ };
38
+ internal.access = { ...apiNode.access };
39
+ if (apiNode.access.nameKey !== null) {
40
+ const key = decryptCryptoBox(sodium.from_hex(apiNode.access.nameKey), apiNode.access.sharedByPubKey, keyPair.privateKey);
41
+ internal.name = sodium.to_string(await decryptSecretstream(key, sodium.from_hex(internal.name)));
42
+ internal.access.nameKey = sodium.to_hex(key);
43
+ }
44
+ for (const b of internal.breadcrumb) {
45
+ if (b.nameKey === null) {
46
+ continue;
47
+ }
48
+ const key = decryptCryptoBox(sodium.from_hex(b.nameKey), b.pubKey, keyPair.privateKey);
49
+ b.nameKey = sodium.to_hex(key);
50
+ b.name = sodium.to_string(await decryptSecretstream(key, sodium.from_hex(b.name)));
51
+ }
52
+ nodesCache.set(internal.id, internal);
53
+ return internal;
54
+ }
55
+ export async function apiNodeFullToInternalFull(apiNodeFull, keyPair) {
56
+ const f = await apiNodeToInternal(apiNodeFull, keyPair);
57
+ return {
58
+ ...f,
59
+ current: apiNodeFull.current !== null
60
+ ? apiFileToInternal(apiNodeFull.current, keyPair)
61
+ : undefined,
62
+ parent: apiNodeFull.parent !== null
63
+ ? await apiNodeToInternal(apiNodeFull.parent, keyPair)
64
+ : null,
65
+ children: await Promise.all(apiNodeFull.children.map(async (s) => await apiNodeToInternal(s, keyPair))),
66
+ history: apiNodeFull.history.map((f) => apiFileToInternal(f, keyPair)),
67
+ };
68
+ }
69
+ export function internalNodeToNode(internal) {
70
+ const node = {
71
+ ...internal,
72
+ breadcrumb: internal.breadcrumb.map((b) => ({
73
+ id: b.id,
74
+ name: b.name,
75
+ })),
76
+ access: {
77
+ isRoot: internal.access.isRoot,
78
+ rights: internal.access.rights,
79
+ sharedByPubKey: internal.access.sharedByPubKey,
80
+ },
81
+ };
82
+ return node;
83
+ }
84
+ export function internalNodeFullToNodeFull(internal) {
85
+ return {
86
+ ...internalNodeToNode(internal),
87
+ parent: internal.parent !== null ? internalNodeToNode(internal.parent) : null,
88
+ children: internal.children.map(internalNodeToNode),
89
+ history: internal.history.map((f) => internalFileToFile(f)),
90
+ current: internal.current !== null && internal.current !== undefined
91
+ ? internalFileToFile(internal.current)
92
+ : undefined,
93
+ };
94
+ }
95
+ export async function apiNodeToExternalNodeFull(apiNodeFull, keyPair) {
96
+ return internalNodeFullToNodeFull(await apiNodeFullToInternalFull(apiNodeFull, keyPair));
97
+ }
98
+ export async function apiNodeToExternal(apiNode, keyPair) {
99
+ return internalNodeToNode(await apiNodeToInternal(apiNode, keyPair));
100
+ }
@@ -0,0 +1,103 @@
1
+ import { SecrecyClient } from './index.js';
2
+ import { popup } from '../utils/popup-tools.js';
3
+ import { secrecyUserApp } from './types/index.js';
4
+ import { getStorage } from './storage.js';
5
+ export function parseInfos() {
6
+ if (window.location.hash === '') {
7
+ return null;
8
+ }
9
+ const hash = window.location.hash.substr(1);
10
+ try {
11
+ const res = JSON.parse(atob(hash));
12
+ window.location.hash = '';
13
+ const data = secrecyUserApp.safeParse(res);
14
+ return data.success ? data.data : null;
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ }
20
+ export const getUrl = ({ hash, path, }) => {
21
+ const lang = document.documentElement.lang;
22
+ const rawAuthUrl = process.env.NEXT_PUBLIC_SECRECY_AUTH_URL ?? 'https://auth.secrecy.me/';
23
+ const authUrl = rawAuthUrl.endsWith('/') ? rawAuthUrl : `${rawAuthUrl}/`;
24
+ path = path.startsWith('/') ? path : `/${path}`;
25
+ return `${authUrl}${lang}${path}#${hash}`;
26
+ };
27
+ export function getSecrecyClient(session) {
28
+ const storage = getStorage(session);
29
+ const uaSession = storage.userAppSession.load();
30
+ const uaKeys = storage.userAppKeys.load();
31
+ const uaJwt = storage.jwt.load();
32
+ if (uaSession === null || uaKeys === null || uaJwt === null) {
33
+ const infos = parseInfos();
34
+ if (infos !== null) {
35
+ storage.userAppKeys.save(infos.keys);
36
+ storage.userAppSession.save(infos.uaSession);
37
+ storage.jwt.save(infos.jwt);
38
+ return new SecrecyClient(infos.uaSession, infos.keys, infos.jwt);
39
+ }
40
+ return null;
41
+ }
42
+ return new SecrecyClient(uaSession, uaKeys, uaJwt);
43
+ }
44
+ export async function login({ appId, path, redirect, scopes, backPath, session, }) {
45
+ return await new Promise((resolve, reject) => {
46
+ const appUrl = window.location.origin;
47
+ const client = getSecrecyClient();
48
+ if (client === null) {
49
+ const infos = {
50
+ appUrl,
51
+ appId,
52
+ redirect,
53
+ path,
54
+ scopes,
55
+ backPath,
56
+ };
57
+ const data = btoa(JSON.stringify(infos)).replaceAll('=', '');
58
+ const url = getUrl({
59
+ hash: data,
60
+ path: 'login',
61
+ });
62
+ const validate = (infos) => {
63
+ const storage = getStorage(session);
64
+ storage.userAppSession.save(infos.uaSession);
65
+ storage.userAppKeys.save(infos.keys);
66
+ storage.jwt.save(infos.jwt);
67
+ resolve(new SecrecyClient(infos.uaSession, infos.keys, infos.jwt));
68
+ };
69
+ if (redirect === true) {
70
+ const infos = parseInfos();
71
+ if (infos !== null) {
72
+ validate(infos);
73
+ }
74
+ else {
75
+ window.location.href = url;
76
+ resolve(null);
77
+ }
78
+ }
79
+ else {
80
+ popup(url, 'Secrecy Login', {
81
+ width: 500,
82
+ height: 750,
83
+ resizable: 'no',
84
+ menubar: 'no',
85
+ location: 'no',
86
+ centered: true,
87
+ scrollbars: 'no',
88
+ }, (err, data) => {
89
+ if (err !== undefined) {
90
+ reject(err);
91
+ }
92
+ else {
93
+ const res = secrecyUserApp.safeParse(data);
94
+ res.success ? validate(res.data) : reject(res.error.message);
95
+ }
96
+ });
97
+ }
98
+ }
99
+ else {
100
+ resolve(client);
101
+ }
102
+ });
103
+ }