Skip to content

Commit

Permalink
Support FindOperator
Browse files Browse the repository at this point in the history
  • Loading branch information
takezoux2 committed Nov 6, 2021
1 parent 456c90e commit 462a979
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 30 deletions.
42 changes: 35 additions & 7 deletions src/transformer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ValueTransformer } from 'typeorm';
import { ValueTransformer, FindOperator, In, Equal, Not } from 'typeorm';
import { EncryptionOptions } from './options';
import { decryptData, encryptData } from './crypto';

Expand All @@ -16,14 +16,42 @@ export class EncryptionTransformer implements ValueTransformer {
).toString('utf8');
}

public to(value?: string | null): string | undefined {
public to(value?: string | FindOperator<any> | null): string | FindOperator<any> | undefined {
if ((value ?? null) === null) {
return;
}

return encryptData(
Buffer.from(value as string, 'utf8'),
this.options
).toString('base64');
if (typeof value === 'string') {
return encryptData(
Buffer.from(value as string, 'utf8'),
this.options
).toString('base64');
}
if (!value) {
return;
}
// Support FindOperator.
// Just support "Equal", "In", "Not", and "IsNull".
// Other operators aren't work correctly, because values are encrypted on the db.
if (value.type === `in`) {
return In((value.value as string[]).map(s =>
encryptData(
Buffer.from(s, 'utf-8'),
this.options
).toString('base64')
));
} else if (value.type === 'equal') {
return Equal(encryptData(
Buffer.from(value.value as string, 'utf-8'),
this.options
).toString('base64'));
} else if (value.type === 'not') {
return Not(
this.to(value.child ?? value.value)
);
} else if (value.type === 'isNull') {
return value
} else {
throw new Error('Only "Equal","In", "Not", and "IsNull" are supported for FindOperator');
}
}
}
21 changes: 1 addition & 20 deletions test/data-mapper.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { expect } from "chai";
import { Connection, In } from "typeorm";
import { Connection } from "typeorm";
import { getConnection } from "./utils";
import ColumnOptionsEntity2 from "./entities/ColumnOptionsEntity2";
import ColumnOptionsEntity4 from "./entities/ColumnOptionsEntity4";

describe("Column Options - Data Mapper", function () {
let connection: Connection;
Expand All @@ -27,22 +26,4 @@ describe("Column Options - Data Mapper", function () {
await repo.clear();
}
});
it("should find by Where In clause", async function () {
const repo = connection.getRepository(ColumnOptionsEntity4);

try {
const secret = "test1"
await repo.save({ secret });

const fromDb = await repo.find({
where: {
secret: In([secret])
}
})
expect(fromDb.length).to.equal(1)

} finally {
await repo.clear()
}
})
});
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
import { ExtendedColumnOptions } from '../../src/options';
import { EncryptionTransformer } from '../../src/transformer';

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

@Column(<ExtendedColumnOptions>{
type: 'varchar',
nullable: false,
encrypt: {
transformer: new EncryptionTransformer({
key: 'e41c966f21f9e1577802463f8924e6a3fe3e9751f201304213b2f845d8841d61',
algorithm: 'aes-256-cbc',
ivLength: 16,
iv: 'ff5ac19190424b1d88f9419ef949ae56'
}
})
})
secret: string;
}
92 changes: 92 additions & 0 deletions test/find-operator.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { expect } from "chai";
import { Connection, In, Not, IsNull, Equal, Like, LessThan } from "typeorm";
import { getConnection } from "./utils";
import TransformerOptionsEntity3 from "./entities/TransformerOptionsEntity3";

describe("Column Options - Data Mapper", function () {
let connection: Connection;

this.timeout(10000);

before(async function () {
connection = await getConnection();
});
it("should find by supported FindOperator", async function () {
const repo = connection.getRepository(TransformerOptionsEntity3);

try {
const secret1 = "test1";
const secret2 = "test2";
await repo.save([{ secret: secret1 }, { secret: secret2 }]);
// Where in
const whereIn = await repo.find({
where: {
secret: In([secret1, secret2])
}
});
expect(whereIn.length).to.equal(2);
expect(whereIn[0].secret).to.equal(secret1);
expect(whereIn[1].secret).to.equal(secret2);
// Where not
const whereNot = await repo.find({
where: {
secret: Not(secret2)
}
});
expect(whereNot.length).to.equal(1);
expect(whereNot[0].secret).to.equal(secret1);
// Where equal
const whereEqual = await repo.find({
where: {
secret: Equal(secret1)
}
});
expect(whereEqual.length).to.equal(1);
expect(whereEqual[0].secret).to.equal(secret1);
// Where not in
const whereNotIn = await repo.find({
where: {
secret: Not(In([secret2]))
}
});
expect(whereNotIn.length).to.equal(1);
expect(whereNotIn[0].secret).to.equal(secret1);
// Where IsNull
const whereIsNull = await repo.find({
where: {
secret: IsNull()
}
});
expect(whereIsNull.length).to.equal(0);
} finally {
await repo.clear();
}
});
it("should throw error by not supported FindOperator", async function () {
const repo = connection.getRepository(TransformerOptionsEntity3);

try {
const secret1 = "test3";
const secret2 = "test4";
await repo.save([{ secret: secret1 }, { secret: secret2 }]);
// Can't use FindOperator except supported ones
for (const notSupportedOperator of [
LessThan(secret1),
Like(secret1)]) {
await repo.find({
where: {
secret: notSupportedOperator
}
}).then( () => {
throw new Error("Never resolved")
}, (reason) => {
expect(reason.message).to.equal(
'Only "Equal","In", "Not", and "IsNull" are supported for FindOperator'
)
});
}
} finally {
await repo.clear();
}
});
});

0 comments on commit 462a979

Please sign in to comment.