add waffle library, handle file upload, authenticate user with oauth and see if they have the link's email associated to their account
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
defmodule Entendu.Links.Link do
|
||||
use Ecto.Schema
|
||||
use Waffle.Ecto.Schema
|
||||
alias Entendu.EncryptedLink
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:id, Ecto.UUID, autogenerate: true}
|
||||
@@ -9,8 +11,8 @@ defmodule Entendu.Links.Link do
|
||||
field :expires, :utc_datetime
|
||||
field :filename, :string
|
||||
field :filetype, :string
|
||||
field :text_content, :string
|
||||
field :file_content, :string
|
||||
field :text_content, EncryptedLink.Type
|
||||
field :file_content, EncryptedLink.Type
|
||||
field :recipient, :string
|
||||
field :service, :string
|
||||
|
||||
@@ -25,10 +27,10 @@ defmodule Entendu.Links.Link do
|
||||
:burn_after_reading,
|
||||
:filename,
|
||||
:filetype,
|
||||
:text_content,
|
||||
:file_content,
|
||||
:recipient,
|
||||
:service
|
||||
])
|
||||
|> cast_attachments(attrs, [:text_content, :file_content])
|
||||
|
||||
end
|
||||
end
|
||||
|
@@ -6,6 +6,7 @@ defmodule Entendu.UserFromAuth do
|
||||
require Jason
|
||||
|
||||
alias Ueberauth.Auth
|
||||
alias Entendu.Links.Link
|
||||
|
||||
def find_or_create(%Auth{} = auth) do
|
||||
{:ok, basic_info(auth)}
|
||||
@@ -24,9 +25,15 @@ defmodule Entendu.UserFromAuth do
|
||||
nil
|
||||
end
|
||||
|
||||
defp emails_from_auth(%Auth{ extra: %Auth.Extra{ raw_info: %{ user: %{ "emails" => emails}}}}), do: emails
|
||||
|
||||
defp emails_from_auth(%Auth{ info: %{ email: email }}), do: [email]
|
||||
|
||||
defp emails_from_auth(_auth), do: []
|
||||
|
||||
defp basic_info(auth) do
|
||||
IO.inspect(auth)
|
||||
%{id: auth.uid, name: name_from_auth(auth), avatar: avatar_from_auth(auth)}
|
||||
%{id: auth.uid, name: name_from_auth(auth), avatar: avatar_from_auth(auth), emails: emails_from_auth(auth)}
|
||||
end
|
||||
|
||||
defp name_from_auth(auth) do
|
||||
@@ -44,4 +51,9 @@ defmodule Entendu.UserFromAuth do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def can_access?(recipient, emails) do
|
||||
emails
|
||||
|> Enum.any?(&( &1["verified"] == true and &1["email"] == recipient))
|
||||
end
|
||||
end
|
||||
|
@@ -23,18 +23,27 @@ defmodule EntenduWeb.AuthController do
|
||||
end
|
||||
|
||||
def callback(%{assigns: %{ueberauth_auth: auth}} = conn, _params) do
|
||||
case UserFromAuth.find_or_create(auth) do
|
||||
{:ok, user} ->
|
||||
# TODO: turn this into plug that only proceeds if current_link session var exists
|
||||
%{ id: link_id, recipient: recipient } = get_session(conn, :current_link)
|
||||
|
||||
with {:ok, user} <- UserFromAuth.find_or_create(auth),
|
||||
true <- UserFromAuth.can_access?(recipient, user.emails) do
|
||||
# TODO: send over encrypted data that the frontend can decrypt
|
||||
conn
|
||||
|> put_flash(:info, "Successfully authenticated.")
|
||||
|> put_session(:current_user, user)
|
||||
|> configure_session(renew: true)
|
||||
|> redirect(to: "/")
|
||||
|> redirect(to: "/just/for/you/#{link_id}")
|
||||
|
||||
else
|
||||
false ->
|
||||
conn
|
||||
|> put_flash(:error, "#{recipient} was not found in your list of verified emails")
|
||||
|> redirect(to: "/just/for/you/#{link_id}")
|
||||
|
||||
{:error, reason} ->
|
||||
conn
|
||||
|> put_flash(:error, reason)
|
||||
|> redirect(to: "/")
|
||||
|> redirect(to: "/just/for/you/#{link_id}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@@ -8,7 +8,6 @@ defmodule EntenduWeb.LinkController do
|
||||
|
||||
alias Entendu.Links
|
||||
alias Links.Link
|
||||
alias Ecto.Changeset
|
||||
alias EntenduWeb.FallbackController
|
||||
|
||||
action_fallback(FallbackController)
|
||||
@@ -17,23 +16,13 @@ defmodule EntenduWeb.LinkController do
|
||||
render(conn, "just.html")
|
||||
end
|
||||
|
||||
defparams(
|
||||
first_step(%{
|
||||
burn_after_reading: [field: :boolean, default: false],
|
||||
expires: :utc_datetime,
|
||||
filename: :string,
|
||||
filetype: :string,
|
||||
text_content: :string,
|
||||
file_content: :string
|
||||
})
|
||||
)
|
||||
|
||||
def just(conn, params) do
|
||||
with %Changeset{valid?: true} = changeset <- first_step(params),
|
||||
link_params <- Params.to_map(changeset),
|
||||
{:ok, %Link{} = link} <- Links.create_link(link_params) do
|
||||
with {:ok, %Link{} = link} <- Links.create_link(params) do
|
||||
conn
|
||||
|> render("show_authorized.json", %{link: link})
|
||||
else
|
||||
test ->
|
||||
IO.inspect(test)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -41,18 +30,9 @@ defmodule EntenduWeb.LinkController do
|
||||
render(conn, "for.html")
|
||||
end
|
||||
|
||||
defparams(
|
||||
second_step(%{
|
||||
service: :string,
|
||||
recipient: :string
|
||||
})
|
||||
)
|
||||
|
||||
def for(conn, %{link_id: link_id} = params) do
|
||||
with %Changeset{valid?: true} = changeset <- first_step(params),
|
||||
link_params <- Params.to_map(changeset),
|
||||
%Link{} = link <- Links.get_link(link_id),
|
||||
Links.update_link(link, link_params) do
|
||||
def for(conn, %{"link_id" => link_id, "recipient" => recipient, "service" => service}) do
|
||||
with %Link{} = link <- Links.get_link(link_id),
|
||||
Links.update_link(link, %{ recipient: recipient, service: service}) do
|
||||
conn
|
||||
|> render("show_authorized.json", %{link: link})
|
||||
end
|
||||
@@ -61,4 +41,12 @@ defmodule EntenduWeb.LinkController do
|
||||
def you_page(conn, _params) do
|
||||
render(conn, "you.html")
|
||||
end
|
||||
|
||||
def auth_page(conn, %{ "id" => link_id}) do
|
||||
with %Link{service: service, recipient: recipient} = link <- Links.get_link(link_id) do
|
||||
conn
|
||||
|> put_session(:current_link, link)
|
||||
|> render("auth.html", %{ service: service, recipient: recipient })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@@ -23,6 +23,7 @@ defmodule EntenduWeb.Router do
|
||||
get "/just/for", LinkController, :for_page
|
||||
post "/just/for", LinkController, :for
|
||||
get "/just/for/you", LinkController, :you_page
|
||||
get "/just/for/you/:id", LinkController, :auth_page
|
||||
end
|
||||
|
||||
scope "/auth", EntenduWeb do
|
||||
|
1
lib/entendu_web/templates/link/auth.html.eex
Normal file
1
lib/entendu_web/templates/link/auth.html.eex
Normal file
@@ -0,0 +1 @@
|
||||
<%= react_component("Components.AuthPage", %{ csrf: Plug.CSRFProtection.get_csrf_token(), service: @service, recipient: @recipient, user: @current_user }) %>
|
@@ -1 +1 @@
|
||||
<%= react_component("Components.ForPage") %>
|
||||
<%= react_component("Components.ForPage", %{ csrf: Plug.CSRFProtection.get_csrf_token() }) %>
|
||||
|
56
lib/entendu_web/uploaders/encrypted_link.ex
Normal file
56
lib/entendu_web/uploaders/encrypted_link.ex
Normal file
@@ -0,0 +1,56 @@
|
||||
defmodule Entendu.EncryptedLink do
|
||||
use Waffle.Definition
|
||||
use Waffle.Ecto.Definition
|
||||
|
||||
# Include ecto support (requires package waffle_ecto installed):
|
||||
# use Waffle.Ecto.Definition
|
||||
|
||||
@versions [:original]
|
||||
|
||||
# To add a thumbnail version:
|
||||
# @versions [:original, :thumb]
|
||||
|
||||
# Override the bucket on a per definition basis:
|
||||
# def bucket do
|
||||
# :custom_bucket_name
|
||||
# end
|
||||
|
||||
# Whitelist file extensions:
|
||||
# def validate({file, _}) do
|
||||
# file_extension = file.file_name |> Path.extname() |> String.downcase()
|
||||
#
|
||||
# case Enum.member?(~w(.jpg .jpeg .gif .png), file_extension) do
|
||||
# true -> :ok
|
||||
# false -> {:error, "invalid file type"}
|
||||
# end
|
||||
# end
|
||||
|
||||
# Define a thumbnail transformation:
|
||||
# def transform(:thumb, _) do
|
||||
# {:convert, "-strip -thumbnail 250x250^ -gravity center -extent 250x250 -format png", :png}
|
||||
# end
|
||||
|
||||
# Override the persisted filenames:
|
||||
# def filename(version, _) do
|
||||
# version
|
||||
# end
|
||||
|
||||
# Override the storage directory:
|
||||
# def storage_dir(version, {file, scope}) do
|
||||
# "uploads/user/avatars/#{scope.id}"
|
||||
# end
|
||||
|
||||
# Provide a default URL if there hasn't been a file uploaded
|
||||
# def default_url(version, scope) do
|
||||
# "/images/avatars/default_#{version}.png"
|
||||
# end
|
||||
|
||||
# Specify custom headers for s3 objects
|
||||
# Available options are [:cache_control, :content_disposition,
|
||||
# :content_encoding, :content_length, :content_type,
|
||||
# :expect, :expires, :storage_class, :website_redirect_location]
|
||||
#
|
||||
# def s3_object_headers(version, {file, scope}) do
|
||||
# [content_type: MIME.from_path(file.file_name)]
|
||||
# end
|
||||
end
|
Reference in New Issue
Block a user