Skip to content

Commit

Permalink
Allow usage of the SQLite-based crypto store (#315)
Browse files Browse the repository at this point in the history
* Allow usage of the SQLite-based crypto store

Signed-off-by: Andrew Ferrazzutti <andrewf@element.io>

* Add types for lowdb

Signed-off-by: Andrew Ferrazzutti <andrewf@element.io>

* Update tests

Signed-off-by: Andrew Ferrazzutti <andrewf@element.io>

* Update examples

Signed-off-by: Andrew Ferrazzutti <andrewf@element.io>

* Fix lint rules for new the imports in examples

Signed-off-by: Andrew Ferrazzutti <andrewf@element.io>

* Test the SQLite crypto store

Run all tests with both the Sled and SQLite store types

Signed-off-by: Andrew Ferrazzutti <andrewf@element.io>

* Fix lint rules

Signed-off-by: Andrew Ferrazzutti <andrewf@element.io>

* Add missing semicolon

Signed-off-by: Andrew Ferrazzutti <andrewf@element.io>

* Apply suggestions from code review

---------

Signed-off-by: Andrew Ferrazzutti <andrewf@element.io>
Co-authored-by: Travis Ralston <travisr@element.io>
  • Loading branch information
AndrewFerr and turt2live authored May 13, 2023
1 parent d4612db commit 943cef4
Show file tree
Hide file tree
Showing 14 changed files with 260 additions and 205 deletions.
4 changes: 3 additions & 1 deletion examples/bot.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { StoreType } from "@matrix-org/matrix-sdk-crypto-nodejs";

import {
AutojoinRoomsMixin,
LogLevel,
Expand Down Expand Up @@ -25,7 +27,7 @@ const dmTarget = creds?.['dmTarget'] ?? "@admin:localhost";
const homeserverUrl = creds?.['homeserverUrl'] ?? "http://localhost:8008";
const accessToken = creds?.['accessToken'] ?? 'YOUR_TOKEN';
const storage = new SimpleFsStorageProvider("./examples/storage/bot.json");
const crypto = new RustSdkCryptoStorageProvider("./examples/storage/bot_sled");
const crypto = new RustSdkCryptoStorageProvider("./examples/storage/bot_sled", StoreType.Sled);

const client = new MatrixClient(homeserverUrl, accessToken, storage, crypto);
AutojoinRoomsMixin.setupOnClient(client);
Expand Down
3 changes: 2 additions & 1 deletion examples/encryption_appservice.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as fs from "fs";
import { StoreType } from "@matrix-org/matrix-sdk-crypto-nodejs";

import {
Appservice,
Expand Down Expand Up @@ -30,7 +31,7 @@ try {
const dmTarget = creds?.['dmTarget'] ?? "@admin:localhost";
const homeserverUrl = creds?.['homeserverUrl'] ?? "http://localhost:8008";
const storage = new SimpleFsStorageProvider("./examples/storage/encryption_appservice.json");
const crypto = new RustSdkAppserviceCryptoStorageProvider("./examples/storage/encryption_appservice_sled");
const crypto = new RustSdkAppserviceCryptoStorageProvider("./examples/storage/encryption_appservice_sled", StoreType.Sled);
const worksImage = fs.readFileSync("./examples/static/it-works.png");

const registration: IAppserviceRegistration = {
Expand Down
3 changes: 2 additions & 1 deletion examples/encryption_bot.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as fs from "fs";
import { StoreType } from "@matrix-org/matrix-sdk-crypto-nodejs";

import {
EncryptionAlgorithm,
Expand Down Expand Up @@ -28,7 +29,7 @@ const dmTarget = creds?.['dmTarget'] ?? "@admin:localhost";
const homeserverUrl = creds?.['homeserverUrl'] ?? "http://localhost:8008";
const accessToken = creds?.['accessToken'] ?? 'YOUR_TOKEN';
const storage = new SimpleFsStorageProvider("./examples/storage/encryption_bot.json");
const crypto = new RustSdkCryptoStorageProvider("./examples/storage/encryption_bot_sled");
const crypto = new RustSdkCryptoStorageProvider("./examples/storage/encryption_bot_sled", StoreType.Sled);
const worksImage = fs.readFileSync("./examples/static/it-works.png");

const client = new MatrixClient(homeserverUrl, accessToken, storage, crypto);
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"tsconfig.json"
],
"dependencies": {
"@matrix-org/matrix-sdk-crypto-nodejs": "0.1.0-beta.3",
"@matrix-org/matrix-sdk-crypto-nodejs": "0.1.0-beta.4",
"@types/express": "^4.17.13",
"another-json": "^0.2.0",
"async-lock": "^1.3.2",
Expand All @@ -76,6 +76,7 @@
"@types/async-lock": "^1.3.0",
"@types/expect": "^24.3.0",
"@types/jest": "^27.5.1",
"@types/lowdb": "^1.0.11",
"@types/mocha": "^8",
"@types/node": "^16",
"@types/simple-mock": "^0.8.2",
Expand Down
7 changes: 6 additions & 1 deletion src/e2ee/CryptoClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,12 @@ export class CryptoClient {

LogService.debug("CryptoClient", "Starting with device ID:", this.deviceId);

const machine = await OlmMachine.initialize(new UserId(await this.client.getUserId()), new DeviceId(this.deviceId), this.storage.storagePath);
const machine = await OlmMachine.initialize(
new UserId(await this.client.getUserId()),
new DeviceId(this.deviceId),
this.storage.storagePath, "",
this.storage.storageType,
);
this.engine = new RustEngine(machine, this.client);
await this.engine.run();

Expand Down
2 changes: 1 addition & 1 deletion src/e2ee/RustEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class RustEngine {
await this.processKeysClaimRequest(request);
break;
case RequestType.ToDevice:
await this.processToDeviceRequest(request);
await this.processToDeviceRequest(request as ToDeviceRequest);
break;
case RequestType.RoomMessage:
throw new Error("Bindings error: Sending room messages is not supported");
Expand Down
20 changes: 13 additions & 7 deletions src/storage/RustSdkCryptoStorageProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,29 @@ import * as mkdirp from "mkdirp";
import * as path from "path";
import * as sha512 from "hash.js/lib/hash/sha/512";
import * as sha256 from "hash.js/lib/hash/sha/256";
import { StoreType as RustSdkCryptoStoreType } from "@matrix-org/matrix-sdk-crypto-nodejs";

import { ICryptoStorageProvider } from "./ICryptoStorageProvider";
import { IAppserviceCryptoStorageProvider } from "./IAppserviceStorageProvider";
import { ICryptoRoomInformation } from "../e2ee/ICryptoRoomInformation";

export { RustSdkCryptoStoreType };

/**
* A crypto storage provider for the default rust-sdk store (sled, file-based).
* A crypto storage provider for the file-based rust-sdk store.
* @category Storage providers
*/
export class RustSdkCryptoStorageProvider implements ICryptoStorageProvider {
private db: any;
private db: lowdb.LowdbSync<any>;

/**
* Creates a new rust-sdk storage provider.
* @param {string} storagePath The *directory* to persist database details to.
*/
public constructor(public readonly storagePath: string) {
public constructor(
public readonly storagePath: string,
public readonly storageType: RustSdkCryptoStoreType = RustSdkCryptoStoreType.Sled,
) {
this.storagePath = path.resolve(this.storagePath);
mkdirp.sync(storagePath);

Expand Down Expand Up @@ -53,21 +59,21 @@ export class RustSdkCryptoStorageProvider implements ICryptoStorageProvider {
}

/**
* An appservice crypto storage provider for the default rust-sdk store (sled, file-based).
* An appservice crypto storage provider for the file-based rust-sdk store.
* @category Storage providers
*/
export class RustSdkAppserviceCryptoStorageProvider extends RustSdkCryptoStorageProvider implements IAppserviceCryptoStorageProvider {
/**
* Creates a new rust-sdk storage provider.
* @param {string} baseStoragePath The *directory* to persist database details to.
*/
public constructor(private baseStoragePath: string) {
super(path.join(baseStoragePath, "_default"));
public constructor(private baseStoragePath: string, storageType: RustSdkCryptoStoreType = RustSdkCryptoStoreType.Sled) {
super(path.join(baseStoragePath, "_default"), storageType);
}

public storageForUser(userId: string): ICryptoStorageProvider {
// sha256 because sha512 is a bit big for some operating systems
const key = sha256().update(userId).digest('hex');
return new RustSdkCryptoStorageProvider(path.join(this.baseStoragePath, key));
return new RustSdkCryptoStorageProvider(path.join(this.baseStoragePath, key), this.storageType);
}
}
14 changes: 7 additions & 7 deletions test/DMsTest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as simple from "simple-mock";

import { EncryptionAlgorithm } from "../src";
import { createTestClient, TEST_DEVICE_ID } from "./TestUtils";
import { createTestClient, testCryptoStores, TEST_DEVICE_ID } from "./TestUtils";

describe('DMs', () => {
it('should update the cache when an sync requests happen', async () => {
Expand Down Expand Up @@ -297,9 +297,9 @@ describe('DMs', () => {
await flush;
});

it('should create an encrypted DM if supported', async () => {
it('should create an encrypted DM if supported', () => testCryptoStores(async (cryptoStoreType) => {
const selfUserId = "@self:example.org";
const { client, http } = createTestClient(null, selfUserId, true);
const { client, http } = createTestClient(null, selfUserId, cryptoStoreType);
const dms = client.dms;

const dmRoomId = "!dm:example.org";
Expand Down Expand Up @@ -359,11 +359,11 @@ describe('DMs', () => {
expect(dms.isDm(dmRoomId)).toBe(true);

await flush;
});
}));

it('should create an unencrypted DM when the target user has no devices', async () => {
it('should create an unencrypted DM when the target user has no devices', () => testCryptoStores(async (cryptoStoreType) => {
const selfUserId = "@self:example.org";
const { client, http } = createTestClient(null, selfUserId, true);
const { client, http } = createTestClient(null, selfUserId, cryptoStoreType);
const dms = client.dms;

const dmRoomId = "!dm:example.org";
Expand Down Expand Up @@ -411,5 +411,5 @@ describe('DMs', () => {
expect(dms.isDm(dmRoomId)).toBe(true);

await flush;
});
}));
});
Loading

0 comments on commit 943cef4

Please sign in to comment.