Add mix task for decrypting uploads
This commit is contained in:
parent
a1dad5d71d
commit
050e6e44a5
|
@ -0,0 +1,23 @@
|
||||||
|
defmodule Mix.Tasks.Wiki.Upload do
|
||||||
|
use Mix.Task
|
||||||
|
alias Wiki.{Repo, Accounts, Accounts.User, Content.Upload}
|
||||||
|
|
||||||
|
@shortdoc "Decrypts an upload into the given file"
|
||||||
|
def run(["decrypt", id, output_file]) do
|
||||||
|
email = IO.gets("Email: ") |> String.trim()
|
||||||
|
password = IO.gets("Password: ") |> String.trim()
|
||||||
|
|
||||||
|
Mix.Task.run("app.start")
|
||||||
|
|
||||||
|
user = Repo.get_by!(User, email: email)
|
||||||
|
upload = Repo.get!(Upload, String.to_integer(id)) |> Repo.preload(:page)
|
||||||
|
|
||||||
|
if upload.page.user_id != user.id do
|
||||||
|
raise "upload owner does not match provided user"
|
||||||
|
else
|
||||||
|
key = Accounts.generate_content_encryption_key(user, %{"password" => password})
|
||||||
|
key = Base.decode16!(key, case: :lower)
|
||||||
|
Upload.decrypt_to_file(upload, key, output_file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -80,7 +80,7 @@ defmodule Wiki.Content.Upload do
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec upload_dir() :: String.t()
|
@spec upload_dir() :: String.t()
|
||||||
defp upload_dir() do
|
def upload_dir() do
|
||||||
dir = Application.get_env(:wiki, :upload_dir)
|
dir = Application.get_env(:wiki, :upload_dir)
|
||||||
|
|
||||||
if is_nil(dir) do
|
if is_nil(dir) do
|
||||||
|
@ -98,6 +98,25 @@ 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_to_file(t(), binary(), String.t()) :: File.t()
|
||||||
|
def decrypt_to_file(upload, key, path) when is_binary(path) do
|
||||||
|
{:ok, output} = File.open(path, [:write, :binary])
|
||||||
|
|
||||||
|
:ok = decrypt_to_file(upload, key, output)
|
||||||
|
|
||||||
|
File.close(output)
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec decrypt_to_file(t(), binary(), File.io_device()) :: File.t()
|
||||||
|
def decrypt_to_file(upload, key, output) do
|
||||||
|
decrypt_stream(upload, key)
|
||||||
|
|> Enum.each(fn data ->
|
||||||
|
IO.binwrite(output, data)
|
||||||
|
end)
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
@spec decrypt_stream(t(), binary()) :: Enumerable.t()
|
@spec decrypt_stream(t(), binary()) :: Enumerable.t()
|
||||||
def decrypt_stream(%__MODULE__{relative_path: filename, encryption_iv: iv}, key) do
|
def decrypt_stream(%__MODULE__{relative_path: filename, encryption_iv: iv}, key) do
|
||||||
start_fun = fn ->
|
start_fun = fn ->
|
||||||
|
@ -125,7 +144,7 @@ defmodule Wiki.Content.Upload do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
after_fun = fn {state, input_dev} ->
|
after_fun = fn {_state, input_dev} ->
|
||||||
File.close(input_dev)
|
File.close(input_dev)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue