Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encryption predicate #71

Merged
merged 4 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export function encrypt<T extends ObjectLiteral>(entity: any): any {
let { propertyName, mode, target } = columnMetadata;
let options: ExtendedColumnOptions = columnMetadata.options;
let encrypt = options.encrypt;
if (encrypt?.encryptionPredicate && !encrypt?.encryptionPredicate(entity)) {
Copy link
Owner

@generalpiston generalpiston Apr 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you merge this with let encrypt = options.encrypt above or with the condition below?

continue;
}
if (
encrypt &&
mode === 'regular' &&
Expand Down Expand Up @@ -42,6 +45,9 @@ export function decrypt<T extends ObjectLiteral>(entity: any): any {
let { propertyName, mode, target } = columnMetadata;
let options: ExtendedColumnOptions = columnMetadata.options;
let encrypt = options.encrypt;
if (encrypt?.encryptionPredicate && !encrypt?.encryptionPredicate(entity)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you merge this with let encrypt = options.encrypt above or with the condition below?

continue;
}
if (
encrypt &&
mode === 'regular' &&
Expand Down
1 change: 1 addition & 0 deletions src/options/EncryptionOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export interface EncryptionOptions {
iv?: string; //// For testing mainly.
authTagLength?: number;
looseMatching?: boolean;
encryptionPredicate?: (entity: any) => boolean;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe change to shouldEncrypt and let it be a function or boolean value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I (respectfully) think we should not do that...

Because the term predicate implies a callable on a condition. shouldEncrypt with dual a usage (bool and a callback) as you propose would be less clear and complicates the if checks in the entity class. Lastly the whole intent is it should resolve to a boolean based on some condition. The condition should not be a hardcode false as that simply turn off encryption on column as a whole, and then why would a user use the encrypt at in the first place.

Unless you disagree with this of course I'm happy to make the change.

}
46 changes: 46 additions & 0 deletions test/encryption-predicate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { expect } from "chai";
import { encrypt, decrypt } from "../src/entity";
import { getConnection } from "./utils";
import ColumnOptionsEntity4 from "./entities/ColumnOptionsEntity4";

describe("Column Options - Encryption Predicate", function () {
this.timeout(10000);

before(async function () {
await getConnection();
});

it("should encrypt", function () {
let result = new ColumnOptionsEntity4();
result.enablePredicate = true;
result.secret = "test";
encrypt(result);
expect(result.secret).to.equal(
"/1rBkZBCSx2I+UGe+UmuVhKzmHsDDv0EvRtMBFiaE3A="
);
});

it("should not encrypt", function () {
let result = new ColumnOptionsEntity4();
result.enablePredicate = false;
result.secret = "test";
encrypt(result);
expect(result.secret).to.equal("test");
});

it("should decrypt", function () {
let result = new ColumnOptionsEntity4();
result.enablePredicate = true;
result.secret = "/1rBkZBCSx2I+UGe+UmuVhKzmHsDDv0EvRtMBFiaE3A=";
decrypt(result);
expect(result.secret).to.equal("test");
});

it("should not decrypt", function () {
let result = new ColumnOptionsEntity4();
result.enablePredicate = false;
result.secret = "test";
decrypt(result);
expect(result.secret).to.equal("test");
});
});
25 changes: 25 additions & 0 deletions test/entities/ColumnOptionsEntity4.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from "typeorm";
import { ExtendedColumnOptions } from "../../src/options";

@Entity()
export default class ColumnOptionsEntity4 extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;

@Column({ type: "boolean" })
enablePredicate: boolean;

@Column(<ExtendedColumnOptions>{
type: "varchar",
nullable: false,
encrypt: {
key: "e41c966f21f9e1577802463f8924e6a3fe3e9751f201304213b2f845d8841d61",
algorithm: "aes-256-cbc",
ivLength: 16,
iv: "ff5ac19190424b1d88f9419ef949ae56",
encryptionPredicate: (entity: ColumnOptionsEntity4) =>
entity.enablePredicate,
},
})
secret: string;
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@
"declaration": true,
"downlevelIteration": true
},
"include": ["src"],
"include": ["src", "test"],
"exclude": ["tmp", "temp", "lib", "node_modules"]
}