Closed chimon2000 closed 4 years ago
Repository metadata isn't passed to subscribers. This makes the data mapper pattern more difficult to support. As a work around, I'll add looseMatching
to the ExtendedColumnOptions
interface.
@pleerock could you advise on passing metadata to the subscribers interface?
@abec can you explain what to you mean and what do you need from typeorm in more details? (remember I don't know typeorm-encrypted internals)
The auto-encrypt mechanism is using an EventSubscriber
@pleerock:
@EventSubscriber()
export class AutoEncryptSubscriber implements EntitySubscriberInterface {
/**
* Encrypt before insertion.
*/
beforeInsert(event: InsertEvent<any>): void {
encrypt(event.entity);
}
/**
* Encrypt before update.
*/
beforeUpdate(event: UpdateEvent<any>): void {
encrypt(event.entity);
}
/**
* Decrypt after find.
*/
afterLoad(entity: any): void {
decrypt(entity);
}
}
The Event
objects have at most to attributes: Entity
and EntityManager
. I don't believe the EntityManager
object has a target or repository associated with it. The encrypt
and decrypt
messages are being passed plain objects when using the data mapper patter like so: userRepository.save({ firstName: 'John', lastName: 'Smith'})
. These plain objects are missing a valid target for filtering:
export function encrypt<T extends ObjectLiteral>(entity: T): T {
for (let columnMetadata of getMetadataArgsStorage().columns) {
let { propertyName, mode, target } = columnMetadata;
let options: ExtendedColumnOptions = columnMetadata.options;
let encrypt = options.encrypt;
if (encrypt && mode === "regular" && (encrypt.looseMatching || entity.constructor === target)) {
if (entity[propertyName]) {
entity[propertyName] = encryptData(Buffer.from(entity[propertyName], "utf8"), encrypt).toString("base64");
}
}
}
return entity;
}
Does it make sense to have the EventSubscriber
include a valid target (ie: https://github.com/typeorm/typeorm/blob/0.1.9/src/repository/Repository.ts#L132)? In the above code, entity.constructor === target
would become entityTarget === target
. I believe to do so, SubjectOperationExecutor
would have to be modified.
@chimon2000 just had a thought... you don't have to use the subscriber to autoencrypt. You can also use the transformers directly (https://github.com/abec/typeorm-encrypted/blob/470da0c7fd23eb1660d26bbb44c5562354a12dfa/src/transformers/index.ts) and use listeners to achieve a similar effect (http://typeorm.io/#/listeners-and-subscribers/what-is-an-entity-listener).
Did anyone find a solution this? I really like the subscriber pattern because it keeps the model clean.
@et I haven't had time to tackle this. If you really need it, we can work together and get this going :).
@abeathos - No worries. I used the hooks and they worked just fine. Thanks!
@et do you mean listeners?
Ah yup. That's what I meant.
Added transformers in #14.
When attempting to use this library with the Data Mapper pattern, the encryption options are ignored. This is because of the following line in the transformer:
entity.constructor === target && mode == "regular"
. When an object is passed into the save/create function, constructor does not exist.Example: