cloak
cloak copied to clipboard
Support encrypted fields in embedded schemas
See #81 and #83.
Because many databases do not support direct encoding and decoding of embeds, it is often emulated by Ecto by using specific encoding and decoding rules.
For example, PostgreSQL will store embeds on top of JSONB columns, which means types in embedded schemas won’t go through the usual dump->DB->load cycle but rather encode->DB->decode->cast. This means that, when using embedded schemas with databases like PG or MySQL, make sure all of your types can be JSON encoded/decoded correctly. Ecto provides this guarantee for all built-in types.
Some thoughts:
- The values would need to be base64 encrypted in order to encode to JSON
- Ecto needs to call Cloak's
dumpfunctions in order to trigger the encryption
I have posted a feature request in Ecto's Google group asking for a needed feature to support this: https://groups.google.com/d/msg/elixir-ecto/RbRdj2NFfDI/qsRLz15nAQAJ
I'd love to see this. Just yesterday I tried using encrypted binaries on an embedded schema and then checked my database... not encrypted.
Another option that would work in my case, would be to use an encrypted Map as the field Ecto stores the embedded_schema in. Not sure how that would work with Ecto needing a map type though.
This feature is now in Ecto. Just add:
def embed_as(_format), do: :dump
To the Ecto type and it should work in future Ecto versions.
Tested this successfully on our app by decoding/encoding the values with 64 as suggested on the initial comment here:
defmodule MyApp.EncodedBinary do
use Cloak.Ecto.Binary, vault: MyApp.Vault
def embed_as(:json), do: :dump
def dump(nil), do: {:ok, nil}
def dump(value) do
with {:ok, encrypted} <- super(value) do
{:ok, Base.encode64(encrypted)}
end
end
def load(nil), do: {:ok, nil}
def load(value), do: super(Base.decode64!(value))
end