Send decrypted upload response as chunked
This commit is contained in:
parent
0d51f9de3d
commit
fd8bf97459
|
@ -98,6 +98,40 @@ defmodule Wiki.Content.Upload do
|
||||||
:crypto.crypto_one_time(:aes_256_ctr, key, iv, encrypted_data, false)
|
:crypto.crypto_one_time(:aes_256_ctr, key, iv, encrypted_data, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec decrypt_stream(t(), binary()) :: Enumerable.t()
|
||||||
|
def decrypt_stream(%__MODULE__{relative_path: filename, encryption_iv: iv}, key) do
|
||||||
|
start_fun = fn ->
|
||||||
|
state = :crypto.crypto_init(:aes_256_ctr, key, iv, false)
|
||||||
|
path = Path.join(upload_dir(), filename)
|
||||||
|
{:ok, input} = File.open(path, [:read, :binary])
|
||||||
|
{state, input, false}
|
||||||
|
end
|
||||||
|
|
||||||
|
next_fun = fn {state, input_dev, halt} ->
|
||||||
|
if halt do
|
||||||
|
{:halt, {state, input_dev}}
|
||||||
|
else
|
||||||
|
# why 4k?
|
||||||
|
{halt, data} =
|
||||||
|
case IO.binread(input_dev, 4096) do
|
||||||
|
:eof ->
|
||||||
|
{true, :crypto.crypto_final(state)}
|
||||||
|
|
||||||
|
data ->
|
||||||
|
{false, :crypto.crypto_update(state, data)}
|
||||||
|
end
|
||||||
|
|
||||||
|
{[data], {state, input_dev, halt}}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
after_fun = fn {state, input_dev} ->
|
||||||
|
File.close(input_dev)
|
||||||
|
end
|
||||||
|
|
||||||
|
Stream.resource(start_fun, next_fun, after_fun)
|
||||||
|
end
|
||||||
|
|
||||||
@spec delete_file(upload :: t()) :: :ok
|
@spec delete_file(upload :: t()) :: :ok
|
||||||
def delete_file(%__MODULE__{relative_path: filename}) do
|
def delete_file(%__MODULE__{relative_path: filename}) do
|
||||||
File.rm(Path.join(upload_dir(), filename))
|
File.rm(Path.join(upload_dir(), filename))
|
||||||
|
|
|
@ -141,11 +141,22 @@ defmodule WikiWeb.PageController do
|
||||||
key = get_session(conn, :content_encryption_key)
|
key = get_session(conn, :content_encryption_key)
|
||||||
key = Base.decode16!(key, case: :lower)
|
key = Base.decode16!(key, case: :lower)
|
||||||
|
|
||||||
data = Upload.decrypt_content(upload, key)
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_resp_header("content-type", upload.content_type)
|
||||||
|
|> send_chunked(200)
|
||||||
|
|
||||||
conn
|
upload
|
||||||
|> put_resp_header("content-type", upload.content_type)
|
|> Upload.decrypt_stream(key)
|
||||||
|> send_resp(200, data)
|
|> Enum.reduce_while(conn, fn decrypted_chunk, conn ->
|
||||||
|
case chunk(conn, decrypted_chunk) do
|
||||||
|
{:ok, conn} ->
|
||||||
|
{:cont, conn}
|
||||||
|
|
||||||
|
{:error, :closed} ->
|
||||||
|
{:halt, {:halt, conn}}
|
||||||
|
end
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_upload(conn, _params) do
|
def delete_upload(conn, _params) do
|
||||||
|
|
Loading…
Reference in New Issue