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
|
||||
|
||||
@spec upload_dir() :: String.t()
|
||||
defp upload_dir() do
|
||||
def upload_dir() do
|
||||
dir = Application.get_env(:wiki, :upload_dir)
|
||||
|
||||
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)
|
||||
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()
|
||||
def decrypt_stream(%__MODULE__{relative_path: filename, encryption_iv: iv}, key) do
|
||||
start_fun = fn ->
|
||||
|
@ -125,7 +144,7 @@ defmodule Wiki.Content.Upload do
|
|||
end
|
||||
end
|
||||
|
||||
after_fun = fn {state, input_dev} ->
|
||||
after_fun = fn {_state, input_dev} ->
|
||||
File.close(input_dev)
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue