loopbackio / loopbackio/loopback-next
Best practice for encrypting model properties
Nessuno ha ancora preso questa issue.
- Lingua principale
- TypeScript
- Stelle
- 5.1k
- Fork
- 1.1k
- Merge medio
- 2g 21h
- PR unite (30g)
- 27
Descrizione
## Description / Steps to reproduce / Feature proposal
In my application, I have models with properties that need to be encrypted before saved in the database.
I'm trying to decide what's the best practice to implement that use-case.
## Current implementation
What I'm currently doing is set an attribute in the property itself:
`encrypted: true`
In my repository, I override the relevant methods. e.g. create:
```
async create(entity: DataObject, options?: AnyObject): Promise {
for (let propertyName in this.entityClass.definition.properties) {
if (this.entityClass.definition.properties[propertyName]['encrypted']) {
entity[propertyName] = encrypted(entity, propertyName)
}
}
return (await super.create(entity, options));
}
```
There are a couple of problems with this implementation.
- This method is not generic, as if tomorrow I would like to implement another logic?
- It requires to override a lot of methods in the repository.
- It requires editing per repository meaning that the CLI only covers a small part of the creation process.
Is there any better implementation for this issue?
## Acceptance criteria
- [ ] A mechanism allowing Repository classes to execute custom code whenever the repository is trying to convert model instance into raw data to be stored and also from the raw data to model instance. This is basically an Operation Hook, and it should be implemented by DefaultCrudRepository. See #2095 (comment) for more details, the code snippet is cross-posted below.
- [ ] A section in our documentation (e.g. in [Key Concepts >> Repositories](https://loopback.io/doc/en/lb4/Repositories.html)) explaining how to use these new mechanism.
- [ ] A guide in our documentation showing how can applications implement property encryption/decryption.
Proposed implementation:
```ts
class DefaultCrudRepository /*...*/{
protected async entityToData(entity: DataObject, options?: Options): DataObject {
// "persist hook" - no-op by default
return entity;
}
protected async dataToEntity(data: DataObject, options?: Options): DataObject {
// "load hook" - no-op by default
return this.toEntity(data);
}
async create(entity: DataObject, options?: Options): Promise {
const data = await this.entityToData(entity, options);
const model = await ensurePromise(this.modelClass.create(data, options));
const result = await this.dataToEntity(model);
return result;
}
// etc.
}
```
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia con DefaultCrudRepository e traccia il create path insieme ai conversion paths corrispondenti descritti nella proposta. Definisci il comportamento degli hook entityToData e dataToEntity, quindi aggiorna la documentazione Key Concepts > Repositories con una guida alla crittografia/decrittografia delle proprietà; il lavoro è completato quando i criteri di accettazione sono coperti.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- typescript
- Ambito
- backend-api-design, documentation
- Tipo di issue
- Funzionalità
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 35/100