Lock files behind temporary token

This commit is contained in:
Chris McCord 2021-11-05 23:02:31 -04:00
parent 287f78ab2a
commit 5f593dfaf2
9 changed files with 46 additions and 10 deletions

2
.gitignore vendored
View file

@ -29,4 +29,4 @@ live_beats-*.tar
npm-debug.log
/assets/node_modules/
/priv/static/uploads
/priv/uploads

View file

@ -38,12 +38,13 @@ Hooks.AudioPlayer = {
this.play()
}
})
this.handleEvent("play", ({url, elapsed}) => {
this.handleEvent("play", ({url, token, elapsed}) => {
this.playbackBeganAt = nowSeconds() - elapsed
if(this.player.src === url && this.player.paused){
let currentSrc = this.player.src.split("?")[0]
if(currentSrc === url && this.player.paused){
this.play({sync: true})
} else if(this.player.src !== url) {
this.player.src = url
} else if(currentSrc !== url) {
this.player.src = `${url}?token=${token}`
this.play({sync: true})
}
})

View file

@ -1,5 +1,11 @@
import Config
config :live_beats, :file_host, %{
scheme: "http",
host: "localhost",
port: 4000
}
config :live_beats, :github, %{
client_id: "83806139172df82d4ccc",
client_secret: System.fetch_env!("LIVE_BEATS_GITHUB_CLIENT_SECRET"),

View file

@ -19,6 +19,10 @@ defmodule LiveBeats.MediaLibrary do
Phoenix.PubSub.subscribe(@pubsub, topic(user.id))
end
def local_filepath(filename_uuid) when is_binary(filename_uuid) do
Path.join("priv/uploads/songs", filename_uuid)
end
def play_song(%Song{id: id}), do: play_song(id)
def play_song(id) do

View file

@ -15,8 +15,9 @@ defmodule LiveBeats.MediaLibrary.Song do
field :duration, :integer
field :status, Ecto.Enum, values: [stopped: 1, playing: 2, paused: 3]
field :title, :string
field :mp3_path, :string
field :mp3_url, :string
field :mp3_filepath, :string
field :mp3_filename, :string
belongs_to :user, Accounts.User
belongs_to :genre, LiveBeats.MediaLibrary.Genre
@ -42,13 +43,19 @@ defmodule LiveBeats.MediaLibrary.Song do
def put_mp3_path(%Ecto.Changeset{} = changeset) do
if changeset.valid? do
filename = Ecto.UUID.generate() <> ".mp3"
filepath = Path.join("priv/static/uploads/songs", filename)
filepath = LiveBeats.MediaLibrary.local_filepath(filename)
changeset
|> Ecto.Changeset.put_change(:mp3_filename, filename)
|> Ecto.Changeset.put_change(:mp3_filepath, filepath)
|> Ecto.Changeset.put_change(:mp3_path, Path.join("uploads/songs", filename))
|> Ecto.Changeset.put_change(:mp3_url, mp3_url(filename))
else
changeset
end
end
defp mp3_url(filename) do
%{scheme: scheme, host: host, port: port} = Application.fetch_env!(:live_beats, :file_host)
URI.to_string(%URI{scheme: scheme, host: host, port: port, path: "/files/#{filename}"})
end
end

View file

@ -0,0 +1,13 @@
defmodule LiveBeatsWeb.FileController do
use LiveBeatsWeb, :controller
alias LiveBeats.MediaLibrary
def show(conn, %{"id" => filename_uuid, "token" => token}) do
case Phoenix.Token.verify(conn, "file", token, max_age: :timer.minutes(10)) do
{:ok, ^filename_uuid} -> send_file(conn, 200, MediaLibrary.local_filepath(filename_uuid))
{:ok, _} -> send_resp(conn, :unauthorized, "")
{:error, _} -> send_resp(conn, :unauthorized, "")
end
end
end

View file

@ -192,10 +192,12 @@ defmodule LiveBeatsWeb.PlayerLive do
end
defp push_play(socket, %Song{} = song, elapsed) do
token = Phoenix.Token.sign(socket.endpoint, "file", song.mp3_filename)
push_event(socket, "play", %{
paused: Song.paused?(song),
elapsed: elapsed,
url: Path.join(LiveBeatsWeb.Endpoint.url(), song.mp3_path)
token: token,
url: song.mp3_url
})
end
end

View file

@ -19,6 +19,8 @@ defmodule LiveBeatsWeb.Router do
scope "/", LiveBeatsWeb do
pipe_through :browser
get "/files/:id", FileController, :show
delete "/signout", OAuthCallbackController, :sign_out
live_session :default, on_mount: [{LiveBeatsWeb.UserAuth, :current_user}, LiveBeatsWeb.Nav] do

View file

@ -10,7 +10,8 @@ defmodule LiveBeats.Repo.Migrations.CreateSongs do
add :played_at, :utc_datetime
add :paused_at, :utc_datetime
add :title, :string, null: false
add :mp3_path, :string, null: false
add :mp3_url, :string, null: false
add :mp3_filename, :string, null: false
add :mp3_filepath, :string, null: false
add :date_recorded, :naive_datetime
add :date_released, :naive_datetime