-
-
Notifications
You must be signed in to change notification settings - Fork 219
feat(orm): add encrypted column decorator with deterministic and blind indexes #1143
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
Open
RomainLanz
wants to merge
32
commits into
22.x
Choose a base branch
from
feat/encryption
base: 22.x
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
735c958
feat(orm): add encrypted column decorator with deterministic and blin…
RomainLanz 8fcfc7b
feat(orm): add encrypted column decorators with driver support and bl…
RomainLanz a1e0adc
fix(orm): encrypt ModelQueryBuilder update payloads and sync blind in…
RomainLanz 3de2e12
fix(orm): avoid encrypting joined table columns with matching names
RomainLanz 1959601
fix(orm): harden encrypted column query/write paths and blind-index h…
RomainLanz 832f316
test(db): include users_encrypted in table snapshots and shared test …
RomainLanz 4d10090
test(db): remove table name
RomainLanz 5c97073
fix(orm): support in/not in operators for encrypted where clauses
RomainLanz 9a1a77f
fix(orm): validate blind encrypted metadata in model write path
RomainLanz 122f944
test(orm): cover unsupported encrypted whereBetween and whereJson ope…
RomainLanz aea389b
fix(orm): harden encrypted where rewriting (in/not in, object, and/or)
RomainLanz 881dfc5
refactor(orm): optimize encrypted update payload preparation in Model…
RomainLanz b80919b
fix(encrypted): exclude driver from column options passed to $addColumn
RomainLanz 10a37e0
refactor(query-builder): deduplicate encrypted where and whereIn logic
RomainLanz d68f680
fix(query-builder): rewrite object where variants for blind multi-ind…
RomainLanz 52f202e
fix(query-builder): guard whereColumn comparisons on encrypted columns
RomainLanz 79cc5a0
refactor(base-model): compute blind index writes in deferred single-p…
RomainLanz 58712d7
refactor(query-builder): validate qualified source before encrypted c…
RomainLanz 9ad4551
fix(encrypted-column): pass driver to decrypt during consume
RomainLanz 90fe535
types(encrypted-column): narrow allowed column options
RomainLanz 8aa33b0
test(query-builder): cover encrypted key/value update with returning
RomainLanz f0dc615
fix(query-builder): reject increment/decrement on encrypted columns
RomainLanz 131629a
test(schema): index blind column on users_encrypted table
RomainLanz 54ea6ce
refactor(query-builder): use named options for encrypted method guards
RomainLanz 79a5a37
fix(query-builder): block object-form increment/decrement on encrypte…
RomainLanz 19a7cb6
fix(base-model): keep encryption provider dynamically inherited after…
RomainLanz 51c3bd0
fix(query-builder): use explicit error for standard encrypted where q…
RomainLanz 3e2df46
fix(encrypted-column): keep driver value as provided and trim only bl…
RomainLanz 2e3d540
chore(errors): reword unsupported encrypted query message for non-whe…
RomainLanz 5d5eca4
refactor(query-builder): simplify encrypted method guard signature
RomainLanz 44fa650
refactor(query-builder): extract encrypted query support into dedicat…
RomainLanz ec11ddb
refactor(encryption): replace useEncryption API with config defaults …
RomainLanz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| /* | ||
| * @adonisjs/lucid | ||
| * | ||
| * (c) AdonisJS | ||
| * | ||
| * For the full copyright and license information, please view the LICENSE | ||
| * file that was distributed with this source code. | ||
| */ | ||
|
|
||
| import * as errors from '../../errors.js' | ||
| import { | ||
| type LucidRow, | ||
| type LucidModel, | ||
| type EncryptedColumnMeta, | ||
| type EncryptedColumnOptions, | ||
| type EncryptedColumnDecorator, | ||
| } from '../../types/model.js' | ||
|
|
||
| function defineEncryptedMeta( | ||
| model: LucidModel, | ||
| property: string, | ||
| options?: EncryptedColumnOptions | ||
| ): EncryptedColumnMeta { | ||
| const dottedAttribute = `${model.name}.${property}` | ||
|
|
||
| if (options?.deterministic && options?.blind) { | ||
| throw new errors.E_INVALID_ENCRYPTED_COLUMN_CONFIGURATION([ | ||
| dottedAttribute, | ||
| 'The "deterministic" and "blind" options cannot be used together', | ||
| ]) | ||
| } | ||
|
|
||
| if (options?.blind) { | ||
| if (!options.blind.columnName?.trim()) { | ||
| throw new errors.E_INVALID_ENCRYPTED_COLUMN_CONFIGURATION([ | ||
| dottedAttribute, | ||
| 'Missing "blind.columnName"', | ||
| ]) | ||
| } | ||
|
|
||
| if (!options.blind.purpose?.trim()) { | ||
| throw new errors.E_INVALID_ENCRYPTED_COLUMN_CONFIGURATION([ | ||
| dottedAttribute, | ||
| 'Missing "blind.purpose"', | ||
| ]) | ||
| } | ||
|
|
||
| return { | ||
| mode: 'blind', | ||
| blindColumnName: options.blind.columnName, | ||
| purpose: options.blind.purpose, | ||
| } | ||
| } | ||
|
|
||
| if (options?.deterministic) { | ||
| return { | ||
| mode: 'deterministic', | ||
| } | ||
| } | ||
|
|
||
| return { | ||
| mode: 'standard', | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Decorator to define an encrypted column | ||
| */ | ||
| export const encryptedColumn: EncryptedColumnDecorator = (options?) => { | ||
| return function decorateAsEncryptedColumn(target, property) { | ||
| const Model = target.constructor as LucidModel | ||
| Model.boot() | ||
|
|
||
| const { | ||
| deterministic: droppedDeterministic, | ||
| blind: droppedBlind, | ||
| ...columnOptions | ||
| } = options || {} | ||
| void droppedDeterministic | ||
| void droppedBlind | ||
|
RomainLanz marked this conversation as resolved.
Outdated
RomainLanz marked this conversation as resolved.
Outdated
|
||
| const encryptionMeta = defineEncryptedMeta(Model, property, options) | ||
| const meta = Object.assign({}, columnOptions.meta, { encryption: encryptionMeta }) | ||
|
|
||
| Model.$addColumn(property, { | ||
| ...columnOptions, | ||
| meta, | ||
| prepare(value: any, attributeName: string, modelInstance: LucidRow) { | ||
| if (value === null || value === undefined) { | ||
| return value | ||
| } | ||
|
|
||
| const encryption = (modelInstance.constructor as LucidModel).$getEncryption(attributeName) | ||
| if (encryptionMeta.mode === 'deterministic') { | ||
| return encryption.encrypt(value, { deterministic: true }) | ||
| } | ||
|
|
||
| return encryption.encrypt(value) | ||
| }, | ||
| consume(value: any, attributeName: string, modelInstance: LucidRow) { | ||
| if (value === null || value === undefined) { | ||
| return value | ||
| } | ||
|
|
||
| const encryption = (modelInstance.constructor as LucidModel).$getEncryption(attributeName) | ||
| return encryption.decrypt(value) | ||
| }, | ||
| }) | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.