@secrecy/lib 1.75.0-feat-groups-identity.1 → 1.75.0-feat-groups-identity.3

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.
@@ -32,7 +32,7 @@ export class SecrecyAppClient {
32
32
  // return this.jwt;
33
33
  // }
34
34
  const { jwt } = await this.#client.apiClient.auth.jwt.query({
35
- includeEmail: typeof this.jwtDecoded.email === 'string',
35
+ includeEmail: typeof this.jwtDecoded['email'] === 'string',
36
36
  });
37
37
  this.jwt = jwt;
38
38
  this.jwtDecoded = decode(jwt);
@@ -463,7 +463,6 @@ export class SecrecyCloudClient {
463
463
  return node;
464
464
  }
465
465
  encryptNodesForIdentities = async (identityNodes) => {
466
- const pubKeys = Object.keys(identityNodes).map((identityPubKey) => identityPubKey);
467
466
  const nodeIds = Object.values(identityNodes).flatMap((nodeIds) => nodeIds);
468
467
  if (nodeIds.length === 0) {
469
468
  return {};
@@ -1,6 +1,3 @@
1
1
  export class SecrecyDbClient {
2
- #client;
3
- constructor(client) {
4
- this.#client = client;
5
- }
2
+ constructor(_client) { }
6
3
  }
@@ -2,6 +2,10 @@ import { dataCache } from '../../cache.js';
2
2
  import { decryptCryptoBox } from '../../crypto/index.js';
3
3
  import { sodium } from '../../sodium.js';
4
4
  export function apiDataToInternal(apiData, keyPairs) {
5
+ const priv = keyPairs[apiData.access.identityPubKey];
6
+ if (priv === undefined) {
7
+ throw new Error(`Missing private key for identityPubKey ${apiData.access.identityPubKey}`);
8
+ }
5
9
  const data = {
6
10
  id: apiData.id,
7
11
  md5: apiData.md5,
@@ -10,7 +14,7 @@ export function apiDataToInternal(apiData, keyPairs) {
10
14
  size: apiData.size,
11
15
  sizeEncrypted: apiData.sizeEncrypted,
12
16
  key: apiData.access.key
13
- ? sodium.to_hex(decryptCryptoBox(sodium.from_hex(apiData.access.key), apiData.access.sharedByPubKey, keyPairs[apiData.access.identityPubKey]))
17
+ ? sodium.to_hex(decryptCryptoBox(sodium.from_hex(apiData.access.key), apiData.access.sharedByPubKey, priv))
14
18
  : null,
15
19
  mime: apiData.mime ?? undefined,
16
20
  ext: apiData.ext ?? undefined,
@@ -10,6 +10,9 @@ export async function convertInternalMailToExternal({ mail, keyPairs, }) {
10
10
  }
11
11
  const pubKey = mail.senderPubKey;
12
12
  const privateKey = keyPairs[mail.recipientPubKey];
13
+ if (privateKey === undefined) {
14
+ throw new Error(`Missing private key for recipientPubKey ${mail.recipientPubKey}`);
15
+ }
13
16
  const body = sodium.to_string(decryptCryptoBox(sodium.from_hex(mail.body), pubKey, privateKey));
14
17
  const subject = sodium.to_string(decryptCryptoBox(sodium.from_hex(mail.subject), pubKey, privateKey));
15
18
  const hash = sodium.crypto_generichash(sodium.crypto_generichash_BYTES, JSON.stringify({ body, subject }), mI.hashKey, 'hex');
@@ -31,19 +31,28 @@ async function apiNodeToInternal(apiNode, keyPairs) {
31
31
  continue;
32
32
  }
33
33
  const pk = keyPairs[access.identityPubKey];
34
+ if (pk === undefined) {
35
+ console.log(access, keyPairs);
36
+ throw new Error(`Missing private key for identityPubKey ${access.identityPubKey}`);
37
+ }
34
38
  const key = decryptCryptoBox(sodium.from_hex(access.nameKey), access.sharedByPubKey, pk);
35
39
  access.nameKey = sodium.to_hex(key);
36
40
  }
37
41
  const firstAccess = internal.accesses[0];
38
- if (!firstAccess || firstAccess.nameKey === null) {
42
+ if (!firstAccess) {
39
43
  throw new Error('No access found for node ' + internal.id);
40
44
  }
41
- internal.name = sodium.to_string(await decryptSecretStream(sodium.from_hex(firstAccess.nameKey), sodium.from_hex(internal.name)));
45
+ if (firstAccess.nameKey !== null) {
46
+ internal.name = sodium.to_string(await decryptSecretStream(sodium.from_hex(firstAccess.nameKey), sodium.from_hex(internal.name)));
47
+ }
42
48
  for (const b of internal.breadcrumb) {
43
49
  if (b.nameKey === null) {
44
50
  continue;
45
51
  }
46
52
  const pk = keyPairs[b.identityPubKey];
53
+ if (pk === undefined) {
54
+ throw new Error(`Missing private key for identityPubKey ${b.identityPubKey}`);
55
+ }
47
56
  const key = decryptCryptoBox(sodium.from_hex(b.nameKey), b.sharedByPubKey, pk);
48
57
  b.nameKey = sodium.to_hex(key);
49
58
  b.name = sodium.to_string(await decryptSecretStream(key, sodium.from_hex(b.name)));
@@ -108,6 +117,9 @@ export async function apiNodeToExternal(apiNode, keyPairs) {
108
117
  export async function apiNodeForEncryptionToInternal(apiNode, keyPairs) {
109
118
  const history = apiNode.history.map((history) => {
110
119
  const pk = keyPairs[history.access.identityPubKey];
120
+ if (pk === undefined) {
121
+ throw new Error(`Missing private key for identityPubKey ${history.access.identityPubKey}`);
122
+ }
111
123
  const key = decryptCryptoBox(sodium.from_hex(history.access.key), history.access.sharedByPublicKey, pk);
112
124
  return {
113
125
  id: history.id,
@@ -124,6 +136,9 @@ export async function apiNodeForEncryptionToInternal(apiNode, keyPairs) {
124
136
  internal.access = { ...apiNode.access };
125
137
  if (apiNode.access.nameKey !== null) {
126
138
  const pk = keyPairs[apiNode.access.identityPubKey];
139
+ if (pk === undefined) {
140
+ throw new Error(`Missing private key for identityPubKey ${apiNode.access.identityPubKey}`);
141
+ }
127
142
  const key = decryptCryptoBox(sodium.from_hex(apiNode.access.nameKey), apiNode.access.sharedByPublicKey, pk);
128
143
  internal.name = sodium.to_string(await decryptSecretStream(key, sodium.from_hex(internal.name)));
129
144
  internal.access.nameKey = sodium.to_hex(key);
@@ -32,7 +32,10 @@ export const downloadDataLinkSchema = z.union([
32
32
  export async function downloadDataFromLink(opts) {
33
33
  let dataUrl = opts.dataUrl ?? 'https://data.secrecy.tech/';
34
34
  dataUrl = dataUrl.endsWith('/') ? dataUrl : `${dataUrl}/`;
35
- const rawDataLink = await fetch(`${dataUrl}${opts.dataLinkSlug}/json`)
35
+ const rawDataLink = await fetch(`${dataUrl}${opts.dataLinkSlug}/json`, {
36
+ mode: 'no-cors',
37
+ credentials: 'include',
38
+ })
36
39
  .then((res) => res.json())
37
40
  .catch((err) => {
38
41
  throw new Error(`Unable to fetch "${`${dataUrl}${opts.dataLinkSlug}/json"`}`, { cause: err });
@@ -41,7 +41,7 @@ export class SecrecyClient extends BaseClient {
41
41
  this.#keyPairs = opts.keyPairs;
42
42
  this.#groupIdentities = opts.identities.filter((i) => i.kind === 'GROUP');
43
43
  const uaIdentities = opts.identities.filter((i) => i.kind === 'USER_APP');
44
- if (uaIdentities.length !== 1) {
44
+ if (!uaIdentities[0]) {
45
45
  throw new Error('One USER_APP identity is required');
46
46
  }
47
47
  this.#uaIdentity = uaIdentities[0];
@@ -9,6 +9,7 @@ export const groupSchema = z.object({
9
9
  kind: z.literal('GROUP'),
10
10
  identityPubKey: z.string(),
11
11
  groupId: z.string(),
12
+ groupRole: z.enum(['ADMIN', 'MEMBER']),
12
13
  sharedByPubKey: z.string(),
13
14
  groupOwnerPubKey: z.string(),
14
15
  });
@@ -160,15 +160,6 @@ export async function uploadData({ storageType, data, password, forcePassword =
160
160
  signal,
161
161
  });
162
162
  if (uploadData.parts.length === 0) {
163
- // TODO why?
164
- // if (
165
- // uploadData.type === 'authed' &&
166
- // (typeof uaIdentity === 'undefined' ||
167
- // typeof uaIdentity === 'string' ||
168
- // uploadData.keyPair.pub !== keyPair.publicKey)
169
- // ) {
170
- // throw new Error('The public key does not match with cached key!')
171
- // }
172
163
  await uploadProgress?.({
173
164
  total: encryptedData.byteLength,
174
165
  current: encryptedData.byteLength,
@@ -46,7 +46,7 @@ function decrypt(header, key) {
46
46
  };
47
47
  }
48
48
  export const CHUNK_SIZE = 8192;
49
- export async function encryptSecretStream(key, data, progress, abort) {
49
+ export async function encryptSecretStream(key, data, progress, signal) {
50
50
  await setup();
51
51
  const { encrypt: crypt, destroy, header } = encrypt(key);
52
52
  const encryptedChunk = CHUNK_SIZE + sodium.crypto_secretstream_xchacha20poly1305_ABYTES;
@@ -69,7 +69,7 @@ export async function encryptSecretStream(key, data, progress, abort) {
69
69
  });
70
70
  let lastPercent = total / max;
71
71
  for (const chunk of chunks(data, CHUNK_SIZE)) {
72
- if (abort?.signal.aborted === true) {
72
+ if (signal?.aborted === true) {
73
73
  throw new Error(`Encrypt aborted`);
74
74
  }
75
75
  spark.append(chunk.buffer);
@@ -102,7 +102,7 @@ export async function encryptSecretStream(key, data, progress, abort) {
102
102
  md5: spark.end(),
103
103
  };
104
104
  }
105
- export async function decryptSecretStream(key, data, progress, abort) {
105
+ export async function decryptSecretStream(key, data, progress, signal) {
106
106
  await setup();
107
107
  const header = data.slice(0, sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES);
108
108
  data = data.slice(sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES);
@@ -118,7 +118,7 @@ export async function decryptSecretStream(key, data, progress, abort) {
118
118
  let total = 0;
119
119
  let lastPercent = total / max;
120
120
  for (const chunk of chunks(data, chunkSize)) {
121
- if (abort?.signal.aborted === true) {
121
+ if (signal?.aborted === true) {
122
122
  throw new Error(`Decrypt aborted`);
123
123
  }
124
124
  const messageTag = decryptFn(chunk);
@@ -43,19 +43,15 @@ const encryptedContentFromParts = async (arg) => {
43
43
  onDownloadProgress: (pr) => {
44
44
  arg.onProgress(`${arg.dataId}-${part.order}`, pr);
45
45
  },
46
- signal: arg.signal,
46
+ signal: arg.signal ?? null,
47
47
  })
48
48
  .arrayBuffer());
49
49
  const md5Part = await md5(buf);
50
50
  if (md5Part !== part.md5) {
51
51
  throw new Error(`Invalid md5 for part ${part.order} of data ${arg.dataId}`);
52
52
  }
53
- if (typeof parts[arg.dataId] === 'undefined') {
54
- parts[arg.dataId] = [{ data: buf, order: part.order }];
55
- }
56
- else {
57
- parts[arg.dataId].push({ data: buf, order: part.order });
58
- }
53
+ parts[arg.dataId] ??= [];
54
+ parts[arg.dataId].push({ data: buf, order: part.order });
59
55
  };
60
56
  await promiseAllLimit(3, arg.dataParts.map((p) => async () => byPart(p)));
61
57
  return concatenate(...parts[arg.dataId].sort((a, b) => a.order - b.order).map((p) => p.data));
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  // lz4-ts @license BSD-3-Clause / Copyright (c) 2015, Pierre Curto / 2016, oov. All rights reserved.
2
3
  /**
3
4
  * Copyright (c) 2015, Pierre Curto
@@ -8,8 +8,8 @@ export const secrecyApplications = [
8
8
  ];
9
9
  function getEnv() {
10
10
  if (typeof window === 'undefined') {
11
- return process.env.VERCEL_ENV
12
- ? process.env.VERCEL_ENV
11
+ return process.env['VERCEL_ENV']
12
+ ? process.env['VERCEL_ENV']
13
13
  : 'production';
14
14
  }
15
15
  if (window.location.hostname.includes('secrecy.tech')) {
@@ -24,10 +24,10 @@ function getEnv() {
24
24
  return 'production';
25
25
  }
26
26
  const env = getEnv();
27
- const secrecyUrl = process.env.NEXT_PUBLIC_IS_SECRECY_INTERNAL !== 'true'
27
+ const secrecyUrl = process.env['NEXT_PUBLIC_IS_SECRECY_INTERNAL'] !== 'true'
28
28
  ? 'www.secrecy.tech'
29
- : (process.env.VERCEL_URL ??
30
- process.env.NEXT_PUBLIC_VERCEL_URL ??
29
+ : (process.env['VERCEL_URL'] ??
30
+ process.env['NEXT_PUBLIC_VERCEL_URL'] ??
31
31
  'www.secrecy.tech');
32
32
  function withPath(origin, path) {
33
33
  if (!path) {
package/dist/lib/utils.js CHANGED
@@ -2,7 +2,7 @@ export const kiloToBytes = (kb) => kb * 1024;
2
2
  export const gigaToBytes = (gb) => gb * 2 ** 30;
3
3
  // Returns the first "primary" email that's found, else returns the first email in the array.
4
4
  export const getPreferedEmail = (emails) => {
5
- if (emails.length === 0) {
5
+ if (!emails[0]) {
6
6
  throw new Error("There's no email!");
7
7
  }
8
8
  return emails.find(({ isPrimary }) => isPrimary) ?? emails[0];
@@ -55,7 +55,7 @@ export const encrypt = process.env.NODE_ENV !== 'test'
55
55
  });
56
56
  }
57
57
  : async (key, dataToEncrypt, progress, signal) => {
58
- return encryptSecretStream(key, dataToEncrypt);
58
+ return encryptSecretStream(key, dataToEncrypt, progress, signal);
59
59
  };
60
60
  export const decrypt = process.env.NODE_ENV !== 'test'
61
61
  ? async (key, dataToDecrypt, progress, signal) => {
@@ -100,5 +100,5 @@ export const decrypt = process.env.NODE_ENV !== 'test'
100
100
  });
101
101
  }
102
102
  : async (key, dataToDecrypt, progress, signal) => {
103
- return decryptSecretStream(key, dataToDecrypt);
103
+ return decryptSecretStream(key, dataToDecrypt, progress, signal);
104
104
  };
@@ -1,4 +1,4 @@
1
- import { type ApiClient, type RouterOutputs, type RouterInputs, CreateTrpcClientOptions } from './client.js';
1
+ import { type ApiClient, type RouterOutputs, type RouterInputs, type CreateTrpcClientOptions } from './client.js';
2
2
  import { type InfuraNetwork, type PublicUser } from './index.js';
3
3
  import { type SelfUser } from './client/types/user.js';
4
4
  export type SecrecyUrls = {
@@ -2,7 +2,7 @@ import type { ProgressCallback, SecrecyClient, UploadDataOptions } from '../inde
2
2
  import type { DataMetadata, DataStorageType, LocalData, Node, NodeFull, NodeType } from './types/index.js';
3
3
  import { type Progress } from '../types.js';
4
4
  import { type RouterInputs, type RouterOutputs } from '../client.js';
5
- import { DownloadDataFromLinkOptions } from './data-link.js';
5
+ import { type DownloadDataFromLinkOptions } from './data-link.js';
6
6
  export declare class SecrecyCloudClient {
7
7
  #private;
8
8
  constructor(client: SecrecyClient);
@@ -1,5 +1,4 @@
1
1
  import type { SecrecyClient } from '../index.js';
2
2
  export declare class SecrecyDbClient {
3
- #private;
4
- constructor(client: SecrecyClient);
3
+ constructor(_client: SecrecyClient);
5
4
  }
@@ -1,4 +1,4 @@
1
- import { RouterInputs, RouterOutputs } from '../client.js';
1
+ import type { RouterInputs, RouterOutputs } from '../client.js';
2
2
  import type { SecrecyClient } from '../index.js';
3
3
  export declare class SecrecyOrganizationClient {
4
4
  #private;
@@ -1,6 +1,6 @@
1
1
  import z from 'zod';
2
- import { ProgressCallback } from '.';
3
- import { Progress } from 'ky';
2
+ import { type ProgressCallback } from '.';
3
+ import { type Progress } from 'ky';
4
4
  export declare const downloadDataLinkSchema: z.ZodUnion<readonly [z.ZodObject<{
5
5
  name: z.ZodString;
6
6
  md5: z.ZodString;
@@ -6,7 +6,7 @@ import { SecrecyAppClient } from './SecrecyAppClient.js';
6
6
  import { SecrecyDbClient } from './SecrecyDbClient.js';
7
7
  import { SecrecyWalletClient } from './SecrecyWalletClient.js';
8
8
  import { SecrecyPayClient } from './SecrecyPayClient.js';
9
- import { ApiClient, type RouterInputs, type RouterOutputs } from '../client.js';
9
+ import { type ApiClient, type RouterInputs, type RouterOutputs } from '../client.js';
10
10
  import { SecrecyUserClient } from './SecrecyUserClient.js';
11
11
  import { SecrecyPseudonymClient } from './SecrecyPseudonymClient.js';
12
12
  import { SecrecyOrganizationClient } from './SecrecyOrganizationClient.js';
@@ -9,6 +9,10 @@ export declare const groupSchema: z.ZodObject<{
9
9
  kind: z.ZodLiteral<"GROUP">;
10
10
  identityPubKey: z.ZodString;
11
11
  groupId: z.ZodString;
12
+ groupRole: z.ZodEnum<{
13
+ ADMIN: "ADMIN";
14
+ MEMBER: "MEMBER";
15
+ }>;
12
16
  sharedByPubKey: z.ZodString;
13
17
  groupOwnerPubKey: z.ZodString;
14
18
  }, z.core.$strip>;
@@ -21,6 +25,10 @@ export declare const accessIdentitySchema: z.ZodDiscriminatedUnion<[z.ZodObject<
21
25
  kind: z.ZodLiteral<"GROUP">;
22
26
  identityPubKey: z.ZodString;
23
27
  groupId: z.ZodString;
28
+ groupRole: z.ZodEnum<{
29
+ ADMIN: "ADMIN";
30
+ MEMBER: "MEMBER";
31
+ }>;
24
32
  sharedByPubKey: z.ZodString;
25
33
  groupOwnerPubKey: z.ZodString;
26
34
  }, z.core.$strip>], "kind">;
@@ -14,6 +14,10 @@ export declare const secrecyUserApp: z.ZodReadonly<z.ZodObject<{
14
14
  kind: z.ZodLiteral<"GROUP">;
15
15
  identityPubKey: z.ZodString;
16
16
  groupId: z.ZodString;
17
+ groupRole: z.ZodEnum<{
18
+ ADMIN: "ADMIN";
19
+ MEMBER: "MEMBER";
20
+ }>;
17
21
  sharedByPubKey: z.ZodString;
18
22
  groupOwnerPubKey: z.ZodString;
19
23
  }, z.core.$strip>], "kind">>;
@@ -1,7 +1,7 @@
1
- import { DataStorageType, LocalData } from './types/data.js';
2
- import { ProgressCallback } from './index.js';
3
- import { FileTypeResult } from 'file-type';
4
- import { ApiClient, RouterInputs } from '../client.js';
1
+ import type { DataStorageType, LocalData } from './types/data.js';
2
+ import type { ProgressCallback } from './index.js';
3
+ import { type FileTypeResult } from 'file-type';
4
+ import { type ApiClient, type RouterInputs } from '../client.js';
5
5
  import type { UserAppIdentity } from './types/identity.js';
6
6
  export type UploadDataOptions = {
7
7
  storageType: DataStorageType;
@@ -10,5 +10,5 @@ export interface SecretStreamProgress {
10
10
  total: number;
11
11
  current: number;
12
12
  }
13
- export declare function encryptSecretStream(key: Uint8Array, data: Uint8Array<ArrayBuffer>, progress?: (progress: SecretStreamProgress) => Promise<void>, abort?: AbortController): Promise<EncryptedFile>;
14
- export declare function decryptSecretStream(key: Uint8Array, data: Uint8Array<ArrayBuffer>, progress?: (progress: SecretStreamProgress) => Promise<void>, abort?: AbortController): Promise<Uint8Array<ArrayBuffer>>;
13
+ export declare function encryptSecretStream(key: Uint8Array, data: Uint8Array<ArrayBuffer>, progress?: (progress: SecretStreamProgress) => Promise<void>, signal?: AbortSignal): Promise<EncryptedFile>;
14
+ export declare function decryptSecretStream(key: Uint8Array, data: Uint8Array<ArrayBuffer>, progress?: (progress: SecretStreamProgress) => Promise<void>, signal?: AbortSignal): Promise<Uint8Array<ArrayBuffer>>;
@@ -1,6 +1,6 @@
1
1
  import { type Progress } from '../types.js';
2
- import { ApiExtendedData } from '../client/types';
3
- import { ProgressCallback } from '../client/index';
2
+ import { type ApiExtendedData } from '../client/types';
3
+ import { type ProgressCallback } from '../client/index';
4
4
  import z from 'zod';
5
5
  import { downloadDataLinkSchema } from '../client/data-link.js';
6
6
  import type { UserAppIdentity } from '../client/types/identity.js';
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@secrecy/lib",
3
3
  "author": "Anonymize <anonymize@gmail.com>",
4
4
  "description": "Anonymize Secrecy Library",
5
- "version": "1.75.0-feat-groups-identity.1",
5
+ "version": "1.75.0-feat-groups-identity.3",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/anonymize-org/lib.git"