Compare commits

..

1 Commits

Author SHA1 Message Date
Marcin Kulik 679a8c78f7 Serve embed script without redirect 7 years ago

@ -1,3 +1 @@
alias Asciinema.{Repo, Asciicasts, Accounts}
alias Asciinema.Asciicasts.Asciicast
alias Asciinema.Accounts.{User, ApiToken}
alias Asciinema.{Repo, Asciicasts, Asciicast, Users, User}

@ -132,23 +132,23 @@ RUN mix deps.get --only prod
# install brunch & co
COPY assets/package.json /app/assets/
RUN cd assets && npm install
COPY package.json /app/
RUN npm install
# compile assets with brunch and generate digest file
COPY assets /app/assets
RUN cd assets && node_modules/brunch/bin/brunch build --production
RUN mix phoenix.digest
COPY brunch-config.js /app/
COPY web/static /app/web/static
RUN node_modules/brunch/bin/brunch build --production && mix phoenix.digest
# add Elixir source files
COPY config/*.exs /app/config/
COPY lib/*.ex /app/lib
COPY lib/asciinema /app/lib/asciinema
COPY lib/asciinema_web /app/lib/asciinema_web
COPY priv/gettext /app/priv/gettext
COPY priv/repo /app/priv/repo
COPY web /app/web
# compile Elixir app

@ -1 +1 @@
../../../assets/static/js/embed.js
../../../web/static/assets/js/embed.js

1
assets/.gitignore vendored

@ -1 +0,0 @@
/node_modules

@ -14,8 +14,8 @@ exports.config = {
// To change the order of concatenation of files, explicitly mention here
order: {
before: [
"vendor/js/jquery-2.2.4.min.js",
"vendor/js/bootstrap.js"
"web/static/vendor/js/jquery-2.2.4.min.js",
"web/static/vendor/js/bootstrap.js"
]
}
},
@ -23,19 +23,19 @@ exports.config = {
joinTo: "css/app.css",
order: {
before: [
"vendor/css/bootstrap.css",
"css/source-sans-pro.css",
"css/base.sass",
"css/header.sass",
"css/flash.sass",
"css/footer.sass",
"css/home.sass",
"css/asciicasts.sass",
"css/users.sass",
"css/preview.sass",
"css/player.sass",
"css/contributing.sass",
"css/simple-layout.sass",
"web/static/vendor/css/bootstrap.css",
"web/static/css/source-sans-pro.css",
"web/static/css/base.sass",
"web/static/css/header.sass",
"web/static/css/flash.sass",
"web/static/css/footer.sass",
"web/static/css/home.sass",
"web/static/css/asciicasts.sass",
"web/static/css/users.sass",
"web/static/css/preview.sass",
"web/static/css/player.sass",
"web/static/css/contributing.sass",
"web/static/css/simple-layout.sass",
]
}
},
@ -46,31 +46,34 @@ exports.config = {
conventions: {
// This option sets where we should place non-css and non-js assets in.
// By default, we set this to "/assets/static". Files in this directory
// By default, we set this to "/web/static/assets". Files in this directory
// will be copied to `paths.public`, which is "priv/static" by default.
assets: /^(static)/
assets: /^(web\/static\/assets)/
},
// Phoenix paths configuration
paths: {
// Dependencies and current project directories to watch
watched: ["static", "css", "js", "vendor"],
watched: [
"web/static",
"test/static"
],
// Where to compile files to
public: "../priv/static"
public: "priv/static"
},
// Configure your plugins
plugins: {
babel: {
// Do not use ES6 compiler in vendor code
ignore: [/vendor/]
ignore: [/web\/static\/vendor/]
}
},
modules: {
autoRequire: {
"js/app.js": ["js/app"]
"js/app.js": ["web/static/js/app"]
}
},

@ -10,10 +10,10 @@ config :asciinema,
ecto_repos: [Asciinema.Repo]
# Configures the endpoint
config :asciinema, AsciinemaWeb.Endpoint,
config :asciinema, Asciinema.Endpoint,
url: [host: "localhost"],
secret_key_base: System.get_env("SECRET_KEY_BASE"),
render_errors: [view: AsciinemaWeb.ErrorView, accepts: ~w(html json)],
render_errors: [view: Asciinema.ErrorView, accepts: ~w(html json)],
pubsub: [name: Asciinema.PubSub,
adapter: Phoenix.PubSub.PG2]

@ -6,24 +6,24 @@ use Mix.Config
# The watchers configuration can be used to run external
# watchers to your application. For example, we use it
# with brunch.io to recompile .js and .css sources.
config :asciinema, AsciinemaWeb.Endpoint,
config :asciinema, Asciinema.Endpoint,
http: [port: 4000],
debug_errors: true,
code_reloader: true,
check_origin: false,
secret_key_base: System.get_env("SECRET_KEY_BASE") || "60BnXnzGGwwiZj91YA9XYKF9BCiM7lQ/1um8VXcWWLSdUp9OcPZV6YnQv7eFTYSY",
watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
cd: Path.expand("../assets", __DIR__)]]
cd: Path.expand("../", __DIR__)]]
# Watch static and templates for browser reloading.
config :asciinema, AsciinemaWeb.Endpoint,
config :asciinema, Asciinema.Endpoint,
live_reload: [
patterns: [
~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
~r{priv/gettext/.*(po)$},
~r{lib/asciinema_web/views/.*(ex)$},
~r{lib/asciinema_web/templates/.*(eex|md)$}
~r{web/views/.*(ex)$},
~r{web/templates/.*(eex|md)$}
]
]

@ -11,12 +11,12 @@ use Mix.Config
# containing the digested version of static files. This
# manifest is generated by the mix phoenix.digest task
# which you typically run after static files are built.
config :asciinema, AsciinemaWeb.Endpoint,
config :asciinema, Asciinema.Endpoint,
http: [port: {:system, "PORT"}],
url: [scheme: System.get_env("URL_SCHEME") || "https",
host: System.get_env("URL_HOST") || "asciinema.org",
port: String.to_integer(System.get_env("URL_PORT") || "443")],
cache_static_manifest: "priv/static/cache_manifest.json"
cache_static_manifest: "priv/static/manifest.json"
# Do not print debug messages in production
config :logger, level: :info
@ -26,7 +26,7 @@ config :logger, level: :info
# To get SSL working, you will need to add the `https` key
# to the previous section and set your `:url` port to 443:
#
# config :asciinema, AsciinemaWeb.Endpoint,
# config :asciinema, Asciinema.Endpoint,
# ...
# url: [host: "example.com", port: 443],
# https: [port: 443,
@ -40,7 +40,7 @@ config :logger, level: :info
# We also recommend setting `force_ssl`, ensuring no data is
# ever sent via http, always redirecting to https:
#
# config :asciinema, AsciinemaWeb.Endpoint,
# config :asciinema, Asciinema.Endpoint,
# force_ssl: [hsts: true]
#
# Check `Plug.SSL` for all available options in `force_ssl`.
@ -55,7 +55,7 @@ config :logger, level: :info
# Alternatively, you can configure exactly which server to
# start per endpoint:
#
# config :asciinema, AsciinemaWeb.Endpoint, server: true
# config :asciinema, Asciinema.Endpoint, server: true
#
config :asciinema, Asciinema.Repo,

@ -2,7 +2,7 @@ use Mix.Config
# We don't run a server during test. If one is required,
# you can enable the server option below.
config :asciinema, AsciinemaWeb.Endpoint,
config :asciinema, Asciinema.Endpoint,
http: [port: 4001],
secret_key_base: "ssecretkeybasesecretkeybasesecretkeybasesecretkeybaseecretkeybase",
server: false

@ -1,6 +0,0 @@
class MakeEmailUnique < ActiveRecord::Migration
def change
remove_index :users, name: "index_users_on_email"
add_index :users, :email, unique: true
end
end

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170803171814) do
ActiveRecord::Schema.define(version: 20170728221839) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -81,7 +81,7 @@ ActiveRecord::Schema.define(version: 20170803171814) do
end
add_index "users", ["auth_token"], name: "index_users_on_auth_token", using: :btree
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["email"], name: "index_users_on_email", using: :btree
add_index "users", ["provider", "uid"], name: "index_users_on_provider_and_uid", unique: true, using: :btree
add_index "users", ["username"], name: "index_users_on_username", using: :btree

@ -1,4 +1,4 @@
defmodule Asciinema.Application do
defmodule Asciinema do
use Application
# See http://elixir-lang.org/docs/stable/elixir/Application.html
@ -13,7 +13,7 @@ defmodule Asciinema.Application do
# Start the Ecto repository
supervisor(Asciinema.Repo, []),
# Start the endpoint when the application starts
supervisor(AsciinemaWeb.Endpoint, []),
supervisor(Asciinema.Endpoint, []),
# Start your own worker by calling: Asciinema.Worker.start_link(arg1, arg2, arg3)
# worker(Asciinema.Worker, [arg1, arg2, arg3]),
:poolboy.child_spec(:worker, Asciinema.PngGenerator.A2png.poolboy_config(), []),
@ -27,4 +27,11 @@ defmodule Asciinema.Application do
opts = [strategy: :one_for_one, name: Asciinema.Supervisor]
Supervisor.start_link(children, opts)
end
# Tell Phoenix to update the endpoint configuration
# whenever the application is updated.
def config_change(changed, _new, removed) do
Asciinema.Endpoint.config_change(changed, removed)
:ok
end
end

@ -1,7 +1,7 @@
defmodule Asciinema.Asciicasts do
import Ecto.Query, warn: false
alias Asciinema.{Repo, FileStore, StringUtils, Vt}
alias Asciinema.Asciicasts.{Asciicast, SnapshotUpdater, FramesGenerator}
alias Asciinema.{Repo, Asciicast, FileStore, StringUtils, Vt}
alias Asciinema.Asciicasts.{SnapshotUpdater, FramesGenerator}
def get_asciicast!(id) when is_integer(id) do
Repo.get!(Asciicast, id)
@ -164,9 +164,9 @@ defmodule Asciinema.Asciicasts do
header = File.open!(path, [:read], fn file -> IO.binread(file, 2) end)
case header do
<<0x1f, 0x8b>> -> # gzip
<<0x1f,0x8b>> -> # gzip
File.open!(path, [:read, :compressed])
<<0x42, 0x5a>> -> # bzip
<<0x42,0x5a>> -> # bzip
{:ok, tmp_path} = Briefly.create()
{_, 0} = System.cmd("sh", ["-c", "bzip2 -d -k -c #{path} >#{tmp_path}"])
File.open!(tmp_path, [:read])

@ -1,5 +1,5 @@
defmodule Asciinema.Asciicasts.FramesGenerator do
alias Asciinema.Asciicasts.Asciicast
alias Asciinema.Asciicast
@doc "Generates frames file for given asciicast"
@callback generate_frames(asciicast :: %Asciicast{}) :: :ok | {:error, term}

@ -1,5 +1,5 @@
defmodule Asciinema.Asciicasts.FramesGenerator.Sidekiq do
alias Asciinema.Asciicasts.Asciicast
alias Asciinema.Asciicast
alias Asciinema.SidekiqClient
def generate_frames(%Asciicast{id: id}) do

@ -1,5 +1,5 @@
defmodule Asciinema.Asciicasts.SnapshotUpdater do
alias Asciinema.Asciicasts.Asciicast
alias Asciinema.Asciicast
@doc "Generates poster for given asciicast"
@callback update_snapshot(asciicast :: %Asciicast{}) :: :ok | {:error, term}

@ -1,6 +1,5 @@
defmodule Asciinema.Asciicasts.SnapshotUpdater.Exq do
alias Asciinema.{Repo, Asciicasts}
alias Asciinema.Asciicasts.Asciicast
alias Asciinema.{Repo, Asciicasts, Asciicast}
def update_snapshot(%Asciicast{id: id}) do
{:ok, _jid} = Exq.enqueue(Exq, "default", __MODULE__, [id])

@ -1,6 +1,5 @@
defmodule Asciinema.Asciicasts.SnapshotUpdater.Sync do
alias Asciinema.Asciicasts
alias Asciinema.Asciicasts.Asciicast
alias Asciinema.{Asciicast, Asciicasts}
def update_snapshot(%Asciicast{} = asciicast) do
{:ok, _} = Asciicasts.update_snapshot(asciicast)

@ -1,10 +1,9 @@
defmodule AsciinemaWeb.Auth do
defmodule Asciinema.Auth do
import Plug.Conn
alias Asciinema.Accounts.User
alias Asciinema.Repo
alias Asciinema.{Repo, User}
@user_key "warden.user.user.key"
@one_year_in_secs 31_557_600
@one_year_in_secs 31557600
def init(opts) do
opts
@ -19,12 +18,10 @@ defmodule AsciinemaWeb.Auth do
assign(conn, :current_user, user)
end
def log_in(conn, %User{} = user) do
user = user |> User.login_changeset |> Repo.update!
def login(conn, %User{id: id, auth_token: auth_token} = user) do
conn
|> put_session(@user_key, user.id)
|> put_resp_cookie("auth_token", user.auth_token, max_age: @one_year_in_secs)
|> put_session(@user_key, id)
|> put_resp_cookie("auth_token", auth_token, max_age: @one_year_in_secs)
|> assign(:current_user, user)
end

@ -1,5 +1,5 @@
defmodule Asciinema.Email do
use Bamboo.Phoenix, view: AsciinemaWeb.EmailView
use Bamboo.Phoenix, view: Asciinema.EmailView
import Bamboo.Email
def signup_email(email_address, signup_url) do
@ -7,7 +7,6 @@ defmodule Asciinema.Email do
|> to(email_address)
|> subject("Welcome to #{instance_hostname()}")
|> render("signup.text", signup_url: signup_url)
|> render("signup.html", signup_url: signup_url)
end
def login_email(email_address, login_url) do
@ -15,14 +14,12 @@ defmodule Asciinema.Email do
|> to(email_address)
|> subject("Login request")
|> render("login.text", login_url: login_url)
|> render("login.html", login_url: login_url)
end
defp base_email do
new_email()
|> from({"asciinema", from_address()})
|> put_header("Reply-To", reply_to_address())
|> put_html_layout({AsciinemaWeb.LayoutView, "email.html"})
end
defp from_address do

@ -1,7 +1,7 @@
defmodule AsciinemaWeb.Endpoint do
defmodule Asciinema.Endpoint do
use Phoenix.Endpoint, otp_app: :asciinema
socket "/socket", AsciinemaWeb.UserSocket
socket "/socket", Asciinema.UserSocket
# Serve at "/" the static files from "priv/static" directory.
#
@ -41,7 +41,7 @@ defmodule AsciinemaWeb.Endpoint do
key_digest: :sha,
serializer: Poison
plug AsciinemaWeb.TrailingFormat
plug Asciinema.TrailingFormat
plug AsciinemaWeb.Router
plug Asciinema.Router
end

@ -1,6 +1,7 @@
defmodule Asciinema.FileStore.Local do
use Asciinema.FileStore
import Plug.Conn
alias Plug.MIME
def put_file(dst_path, src_local_path, _content_type, _compress \\ false) do
full_dst_path = base_path() <> dst_path
@ -23,7 +24,7 @@ defmodule Asciinema.FileStore.Local do
defp do_serve_file(conn, path) do
conn
|> put_resp_header("content-type", MIME.from_path(path))
|> put_resp_header("content-type", MIME.path(path))
|> send_file(200, base_path() <> path)
|> halt
end

@ -5,7 +5,7 @@ defmodule Asciinema.FileStore.S3 do
def put_file(dst_path, src_local_path, content_type, compress \\ false) do
{body, opts} = if compress do
body = src_local_path |> File.read! |> :zlib.gzip
body = File.read!(src_local_path) |> :zlib.gzip
opts = [{:content_type, content_type}, {:content_encoding, "gzip"}]
{body, opts}
else
@ -36,20 +36,23 @@ defmodule Asciinema.FileStore.S3 do
end
def open_file(path, function \\ nil) do
response = bucket() |> S3.get_object(base_path() <> path) |> make_request
response = S3.get_object(bucket(), base_path() <> path) |> make_request
with {:ok, %{headers: headers, body: body}} <- response do
body =
case List.keyfind(headers, "Content-Encoding", 0) do
{"Content-Encoding", "gzip"} -> :zlib.gunzip(body)
_ -> body
end
case response do
{:ok, %{headers: headers, body: body}} ->
body =
case List.keyfind(headers, "Content-Encoding", 0) do
{"Content-Encoding", "gzip"} -> :zlib.gunzip(body)
_ -> body
end
if function do
File.open(body, [:ram, :binary, :read], function)
else
File.open(body, [:ram, :binary, :read])
end
if function do
File.open(body, [:ram, :binary, :read], function)
else
File.open(body, [:ram, :binary, :read])
end
{:error, reason} ->
{:error, reason}
end
end

@ -1,5 +1,5 @@
defmodule Asciinema.PngGenerator do
alias Asciinema.Asciicasts.Asciicast
alias Asciinema.Asciicast
alias Asciinema.PngGenerator.PngParams
@doc "Generates PNG image from asciicast and returns path to it"

@ -1,13 +1,13 @@
defmodule Asciinema.PngGenerator.A2png do
@behaviour Asciinema.PngGenerator
use GenServer
alias Asciinema.Asciicasts.Asciicast
alias Asciinema.Asciicast
alias Asciinema.PngGenerator.PngParams
@pool_name :worker
@acquire_timeout 5000
@a2png_timeout 30_000
@result_timeout 35_000
@a2png_timeout 30000
@result_timeout 35000
def generate(%Asciicast{} = asciicast, %PngParams{} = png_params) do
{:ok, tmp_dir_path} = Briefly.create(directory: true)

@ -1,4 +1,4 @@
defmodule AsciinemaWeb.Rails.Flash do
defmodule Asciinema.Rails.Flash do
import Plug.Conn
def put_rails_flash(conn, key, value) do

@ -1,4 +1,4 @@
defmodule AsciinemaWeb.TrailingFormat do
defmodule Asciinema.TrailingFormat do
@known_extensions ["js", "json", "png", "gif"]
def init(opts), do: opts

@ -1,8 +1,7 @@
defmodule Asciinema.Accounts do
defmodule Asciinema.Users do
import Ecto.Query, warn: false
import Ecto, only: [assoc: 2]
alias Asciinema.Accounts.{User, ApiToken}
alias Asciinema.{Repo, Asciicasts, Email, Mailer}
alias Asciinema.{Repo, User, ApiToken, Asciicasts, Email, Mailer, Auth}
def create_asciinema_user!() do
attrs = %{username: "asciinema",
@ -80,25 +79,25 @@ defmodule Asciinema.Accounts do
{:ok, url}
end
def signup_url(email) do
token = Phoenix.Token.sign(AsciinemaWeb.Endpoint, "signup", email)
AsciinemaWeb.Router.Helpers.users_url(AsciinemaWeb.Endpoint, :new, t: token)
defp signup_url(email) do
token = Phoenix.Token.sign(Asciinema.Endpoint, "signup", email)
Asciinema.Router.Helpers.users_url(Asciinema.Endpoint, :new, t: token)
end
def login_url(%User{id: id, last_login_at: last_login_at}) do
defp login_url(%User{id: id, last_login_at: last_login_at}) do
last_login_at = last_login_at && Timex.to_unix(last_login_at)
token = Phoenix.Token.sign(AsciinemaWeb.Endpoint, "login", {id, last_login_at})
AsciinemaWeb.Router.Helpers.session_url(AsciinemaWeb.Endpoint, :new, t: token)
token = Phoenix.Token.sign(Asciinema.Endpoint, "login", {id, last_login_at})
Asciinema.Router.Helpers.session_url(Asciinema.Endpoint, :new, t: token)
end
@login_token_max_age 15 * 60 # 15 minutes
alias Phoenix.Token
alias AsciinemaWeb.Endpoint
alias Asciinema.Endpoint
def verify_signup_token(token) do
with {:ok, email} <- Token.verify(Endpoint, "signup", token, max_age: @login_token_max_age),
{:ok, %User{} = user} <- Repo.insert(User.signup_changeset(%{email: email})) do
{:ok, %User{} = user} <- User.signup_changeset(%{email: email}) |> Repo.insert do
{:ok, user}
else
{:error, :invalid} ->
@ -125,6 +124,11 @@ defmodule Asciinema.Accounts do
end
end
def log_in(conn, %User{} = user) do
user = user |> User.login_changeset |> Repo.update!
Auth.login(conn, user)
end
def authenticate(api_token) do
q = from u in User,
join: at in ApiToken,

@ -65,7 +65,7 @@ defmodule Asciinema.Vt.Worker do
end
defp send_cmd(port, cmd, data \\ %{}) do
json = data |> Map.put(:cmd, cmd) |> Poison.encode!
json = Map.put(data, :cmd, cmd) |> Poison.encode!
true = Port.command(port, "#{json}\n")
end
end

@ -1,10 +0,0 @@
<p>Hello,</p>
<p>Click the following link to log in to asciinema.org:</p>
<p><a href="<%= @login_url %>"><%= @login_url %></a></p>
<p>
<br>
If you did not initiate this request, just ignore this email. The request will expire shortly.
</p>

@ -1,10 +0,0 @@
<p>Welcome,</p>
<p>Click the following link to create your account at asciinema.org:</p>
<p><a href="<%= @signup_url %>"><%= @signup_url %></a></p>
<p>
<br>
If you did not initiate this request, just ignore this email. The request will expire shortly.
</p>

@ -1 +0,0 @@
<%= render @view_module, "wrapper.html", Map.merge(assigns, %{layout: {AsciinemaWeb.LayoutView, "app.html"}, topic_template: @view_template}) %>

@ -1,9 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<%= render @view_module, @view_template, assigns %>
</body>
</html>

@ -1,3 +0,0 @@
defmodule AsciinemaWeb.AsciicastAnimationView do
use AsciinemaWeb, :view
end

@ -1,3 +0,0 @@
defmodule AsciinemaWeb.EmailView do
use AsciinemaWeb, :view
end

@ -1,3 +0,0 @@
defmodule AsciinemaWeb.LoginView do
use AsciinemaWeb, :view
end

@ -1,3 +0,0 @@
defmodule AsciinemaWeb.SessionView do
use AsciinemaWeb, :view
end

@ -17,7 +17,7 @@ defmodule Asciinema.Mixfile do
#
# Type `mix help compile.app` for more information.
def application do
[mod: {Asciinema.Application, []},
[mod: {Asciinema, []},
applications: [
:bamboo,
:bamboo_smtp,
@ -44,8 +44,8 @@ defmodule Asciinema.Mixfile do
end
# Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]
defp elixirc_paths(:test), do: ["lib", "web", "test/support"]
defp elixirc_paths(_), do: ["lib", "web"]
# Specifies your project dependencies.
#
@ -57,14 +57,13 @@ defmodule Asciinema.Mixfile do
{:briefly, "~> 0.3"},
{:bugsnag, "~> 1.5.0"},
{:cowboy, "~> 1.0"},
{:credo, "~> 0.8", only: [:dev, :test], runtime: false},
{:ex_aws, "~> 1.0"},
{:exq, "~> 0.9.0"},
{:exq_ui, "~> 0.9.0"},
{:gettext, "~> 0.11"},
{:phoenix, "~> 1.3.0"},
{:phoenix, "~> 1.2.1"},
{:phoenix_ecto, "~> 3.0"},
{:phoenix_html, "~> 2.10"},
{:phoenix_html, "~> 2.6"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:phoenix_markdown, "~> 0.1"},
{:phoenix_pubsub, "~> 1.0"},

@ -2,46 +2,44 @@
"bamboo_smtp": {:hex, :bamboo_smtp, "1.4.0", "a01d91406f3a46b3452c84d345d50f75d6facca5e06337358287a97da0426240", [:mix], [{:bamboo, "~> 0.8.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:gen_smtp, "~> 0.12.0", [hex: :gen_smtp, repo: "hexpm", optional: false]}], "hexpm"},
"briefly": {:hex, :briefly, "0.3.0", "16e6b76d2070ebc9cbd025fa85cf5dbaf52368c4bd896fb482b5a6b95a540c2f", [:mix], [], "hexpm"},
"bugsnag": {:hex, :bugsnag, "1.5.0", "e761b3c4c198d01d4b04b85298ea7756632c70610ed0b1a57f04c2f528a3e3ab", [:mix], [{:httpoison, "~> 0.9", [hex: :httpoison, repo: "hexpm", optional: false]}, {:poison, "~> 1.5 or ~> 2.0 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
"certifi": {:hex, :certifi, "1.0.0", "1c787a85b1855ba354f0b8920392c19aa1d06b0ee1362f9141279620a5be2039", [:rebar3], [], "hexpm"},
"combine": {:hex, :combine, "0.9.6", "8d1034a127d4cbf6924c8a5010d3534d958085575fa4d9b878f200d79ac78335", [:mix], [], "hexpm"},
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
"cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm"},
"credo": {:hex, :credo, "0.8.4", "4e50acac058cf6292d6066e5b0d03da5e1483702e1ccde39abba385c9f03ead4", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"},
"db_connection": {:hex, :db_connection, "1.1.2", "2865c2a4bae0714e2213a0ce60a1b12d76a6efba0c51fbda59c9ab8d1accc7a8", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
"decimal": {:hex, :decimal, "1.4.0", "fac965ce71a46aab53d3a6ce45662806bdd708a4a95a65cde8a12eb0124a1333", [:mix], [], "hexpm"},
"db_connection": {:hex, :db_connection, "1.0.0-rc.5", "1d9ab6e01387bdf2de7a16c56866971f7c2f75aea7c69cae2a0346e4b537ae0d", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0.0-beta.3", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
"decimal": {:hex, :decimal, "1.1.2", "79a769d4657b2d537b51ef3c02d29ab7141d2b486b516c109642d453ee08e00c", [:mix], [], "hexpm"},
"earmark": {:hex, :earmark, "1.2.2", "f718159d6b65068e8daeef709ccddae5f7fdc770707d82e7d126f584cd925b74", [:mix], [], "hexpm"},
"ecto": {:hex, :ecto, "2.1.4", "d1ba932813ec0e0d9db481ef2c17777f1cefb11fc90fa7c142ff354972dfba7e", [:mix], [{:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
"ecto": {:hex, :ecto, "2.0.4", "03fd3b9aa508b1383eb38c00ac389953ed22af53811aa2e504975a3e814a8d97", [:mix], [{:db_connection, "~> 1.0-rc.2", [hex: :db_connection, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.7.7", [hex: :mariaex, repo: "hexpm", optional: true]}, {:poison, "~> 1.5 or ~> 2.0", [hex: :poison, repo: "hexpm", optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.11.2", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0-beta", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
"ex_aws": {:hex, :ex_aws, "1.1.2", "b78416d0a84efe92c22e5df8ba7ca028d63b2b4228f95871a1ecf10324b6493b", [:mix], [{:configparser_ex, "~> 0.2.1", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "1.6.3 or 1.6.5 or 1.7.1", [hex: :hackney, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8", [hex: :jsx, repo: "hexpm", optional: true]}, {:poison, ">= 1.2.0", [hex: :poison, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:xml_builder, "~> 0.0.6", [hex: :xml_builder, repo: "hexpm", optional: true]}], "hexpm"},
"exq": {:hex, :exq, "0.9.0", "3feeb085fcd94a687033211e10c78cf9dca1de062aac3fa9a4b1f808cdcea522", [:mix], [{:poison, ">= 1.2.0 or ~> 2.0", [hex: :poison, repo: "hexpm", optional: false]}, {:redix, ">= 0.5.0", [hex: :redix, repo: "hexpm", optional: false]}, {:uuid, ">= 1.0.0", [hex: :uuid, repo: "hexpm", optional: false]}], "hexpm"},
"exq_ui": {:hex, :exq_ui, "0.9.0", "e97e9fa9009f30d2926b51a166e40a3a521e83f61f3f333fede8335b2aa57f09", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: false]}, {:exq, "~> 0.9", [hex: :exq, repo: "hexpm", optional: false]}, {:plug, ">= 0.8.1 and < 2.0.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], [], "hexpm"},
"gen_smtp": {:hex, :gen_smtp, "0.12.0", "97d44903f5ca18ca85cb39aee7d9c77e98d79804bbdef56078adcf905cb2ef00", [:rebar3], [], "hexpm"},
"gettext": {:hex, :gettext, "0.13.1", "5e0daf4e7636d771c4c71ad5f3f53ba09a9ae5c250e1ab9c42ba9edccc476263", [:mix], [], "hexpm"},
"gettext": {:hex, :gettext, "0.11.0", "80c1dd42d270482418fa158ec5ba073d2980e3718bacad86f3d4ad71d5667679", [:mix], [], "hexpm"},
"hackney": {:hex, :hackney, "1.7.1", "e238c52c5df3c3b16ce613d3a51c7220a784d734879b1e231c9babd433ac1cb4", [:rebar3], [{:certifi, "1.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "4.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"httpoison": {:hex, :httpoison, "0.11.1", "d06c571274c0e77b6cc50e548db3fd7779f611fbed6681fd60a331f66c143a0b", [:mix], [{:hackney, "~> 1.7.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
"idna": {:hex, :idna, "4.0.0", "10aaa9f79d0b12cf0def53038547855b91144f1bfcc0ec73494f38bb7b9c4961", [:rebar3], [], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
"mime": {:hex, :mime, "1.1.0", "01c1d6f4083d8aa5c7b8c246ade95139620ef8effb009edde934e0ec3b28090a", [:mix], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
"phoenix": {:hex, :phoenix, "1.3.0", "1c01124caa1b4a7af46f2050ff11b267baa3edb441b45dbf243e979cd4c5891b", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_ecto": {:hex, :phoenix_ecto, "3.2.3", "450c749876ff1de4a78fdb305a142a76817c77a1cd79aeca29e5fc9a6c630b26", [:mix], [{:ecto, "~> 2.1", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_html": {:hex, :phoenix_html, "2.10.2", "0249cc636c9fb4ac4c84a6075e3e352ca5e31fd4756142bc9e31d73fd507a62a", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.0.8", "4333f9c74190f485a74866beff2f9304f069d53f047f5fbb0fb8d1ee4c495f73", [:mix], [{:fs, "~> 0.9.1", [hex: :fs, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.0 or ~> 1.2-rc", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix": {:hex, :phoenix, "1.2.3", "b68dd6a7e6ff3eef38ad59771007d2f3f344988ea6e658e9b2c6ffb2ef494810", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.4 or ~> 1.3.3 or ~> 1.2.4 or ~> 1.1.8 or ~> 1.0.5", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 1.5 or ~> 2.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_ecto": {:hex, :phoenix_ecto, "3.0.1", "42eb486ef732cf209d0a353e791806721f33ff40beab0a86f02070a5649ed00a", [:mix], [{:ecto, "~> 2.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.6", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_html": {:hex, :phoenix_html, "2.9.3", "1b5a2122cbf743aa242f54dced8a4f1cc778b8bd304f4b4c0043a6250c58e258", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.0.5", "829218c4152ba1e9848e2bf8e161fcde6b4ec679a516259442561d21fde68d0b", [:mix], [{:fs, "~> 0.9.1", [hex: :fs, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.0 or ~> 1.2-rc", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_markdown": {:hex, :phoenix_markdown, "0.1.4", "246727d998997c6b90374a678bbdca5b300dcbbfecb29dbcca8a7891751f6cd5", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.1", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.3", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.0.2", "bfa7fd52788b5eaa09cb51ff9fcad1d9edfeb68251add458523f839392f034c1", [:mix], [], "hexpm"},
"plug": {:hex, :plug, "1.4.3", "236d77ce7bf3e3a2668dc0d32a9b6f1f9b1f05361019946aae49874904be4aed", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.0.1", "c10ddf6237007c804bf2b8f3c4d5b99009b42eca3a0dfac04ea2d8001186056a", [:mix], [], "hexpm"},
"plug": {:hex, :plug, "1.3.5", "7503bfcd7091df2a9761ef8cecea666d1f2cc454cbbaf0afa0b6e259203b7031", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"},
"plug_rails_cookie_session_store": {:hex, :plug_rails_cookie_session_store, "0.1.0", "8d87967eb2d4d25837e1b5778265aebf8ac797291d6ff65dbd828c4ffa7f0955", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: true]}, {:plug, ">= 0.9.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"plugsnag": {:git, "https://github.com/sickill/plugsnag.git", "a5d8dcc370f52cec9fcf21acb42e2b293b003b37", []},
"poison": {:hex, :poison, "2.2.0", "4763b69a8a77bd77d26f477d196428b741261a761257ff1cf92753a0d4d24a63", [:mix], [], "hexpm"},
"poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], [], "hexpm"},
"porcelain": {:hex, :porcelain, "2.0.3", "2d77b17d1f21fed875b8c5ecba72a01533db2013bd2e5e62c6d286c029150fdc", [:mix], [], "hexpm"},
"postgrex": {:hex, :postgrex, "0.13.3", "c277cfb2a9c5034d445a722494c13359e361d344ef6f25d604c2353185682bfc", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"},
"postgrex": {:hex, :postgrex, "0.11.2", "139755c1359d3c5c6d6e8b1ea72556d39e2746f61c6ddfb442813c91f53487e8", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 1.0-rc", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"},
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"},
"redix": {:hex, :redix, "0.6.1", "20986b0e02f02b13e6f53c79a1ae70aa83147488c408f40275ec261f5bb0a6d0", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
"timex": {:hex, :timex, "3.1.24", "d198ae9783ac807721cca0c5535384ebdf99da4976be8cefb9665a9262a1e9e3", [:mix], [{:combine, "~> 0.7", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
"timex_ecto": {:hex, :timex_ecto, "3.1.1", "37d54f6879d96a6789bb497296531cfb853631de78e152969d95cff03c1368dd", [:mix], [{:ecto, "~> 2.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:timex, "~> 3.0", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm"},
"timex": {:hex, :timex, "3.1.15", "94abaec8fef2436ced4d0e1b4ed50c8eaa5fb9138fc0699946ddee7abf5aaff2", [:mix], [{:combine, "~> 0.7", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
"timex_ecto": {:hex, :timex_ecto, "3.0.5", "3ec6c25e10d2c0020958e5df64d2b5e690e441faa2c2259da8bc6bd3d7f39256", [:mix], [{:ecto, "~> 2.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:timex, "~> 3.0", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm"},
"tzdata": {:hex, :tzdata, "0.5.12", "1c17b68692c6ba5b6ab15db3d64cc8baa0f182043d5ae9d4b6d35d70af76f67b", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
"uuid": {:hex, :uuid, "1.1.7", "007afd58273bc0bc7f849c3bdc763e2f8124e83b957e515368c498b641f7ab69", [:mix], [], "hexpm"}}

@ -6,16 +6,16 @@
"watch": "brunch watch --stdin"
},
"dependencies": {
"phoenix": "file:../deps/phoenix",
"phoenix_html": "file:../deps/phoenix_html"
"phoenix": "file:deps/phoenix",
"phoenix_html": "file:deps/phoenix_html"
},
"devDependencies": {
"babel-brunch": "6.0.6",
"brunch": "2.10.7",
"clean-css-brunch": "2.10.0",
"babel-brunch": "~6.0.0",
"brunch": "2.7.4",
"clean-css-brunch": "~2.0.0",
"css-brunch": "~2.0.0",
"sass-brunch": "^2.6.3",
"javascript-brunch": "~2.0.0",
"uglify-js-brunch": "2.1.1"
"uglify-js-brunch": "~2.0.1"
}
}

@ -1,7 +1,6 @@
defmodule Asciinema.AsciicastsTest do
use Asciinema.DataCase
alias Asciinema.Asciicasts
alias Asciinema.Asciicasts.Asciicast
alias Asciinema.{Asciicasts, Asciicast}
describe "create_asciicast/3" do
test "json file, v0 format with uname" do

@ -1,12 +1,11 @@
defmodule Asciinema.AccountsTest do
defmodule Asciinema.UsersTest do
import Asciinema.Fixtures
use Asciinema.DataCase
use Bamboo.Test
alias Asciinema.Email
alias Asciinema.Accounts.User
describe "send_login_email/1" do
import Asciinema.Accounts, only: [send_login_email: 1]
import Asciinema.Users, only: [send_login_email: 1]
test "existing user, by email" do
user = fixture(:user)
@ -35,18 +34,4 @@ defmodule Asciinema.AccountsTest do
assert_no_emails_delivered()
end
end
describe "verify_signup_token/1" do
import Asciinema.Accounts, only: [verify_signup_token: 1, signup_url: 1]
test "invalid token" do
assert verify_signup_token("invalid") == {:error, :token_invalid}
end
test "valid token" do
token = "test@example.com" |> signup_url |> String.split("?t=") |> List.last
assert {:ok, %User{}} = verify_signup_token(token)
assert verify_signup_token(token) == {:error, :email_taken}
end
end
end

@ -1,6 +1,6 @@
defmodule Asciinema.Api.AsciicastControllerTest do
use AsciinemaWeb.ConnCase
alias Asciinema.Accounts
use Asciinema.ConnCase
alias Asciinema.Users
setup %{conn: conn} = context do
token = Map.get(context, :token, "9da34ff4-9bf7-45d4-aa88-98c933b15a3f")
@ -84,7 +84,7 @@ defmodule Asciinema.Api.AsciicastControllerTest do
end
test "existing user (API token)", %{conn: conn, token: token} do
{:ok, _} = Accounts.create_user_with_api_token(token, "test")
{:ok, _} = Users.create_user_with_api_token(token, "test")
upload = fixture(:upload, %{path: "1/asciicast.json"})
conn = post conn, api_asciicast_path(conn, :create), %{"asciicast" => upload}
assert text_response(conn, 201) =~ @asciicast_url
@ -99,8 +99,8 @@ defmodule Asciinema.Api.AsciicastControllerTest do
end
test "authentication with revoked token", %{conn: conn, token: token} do
Accounts.get_user_with_api_token(token, "test") # force registration of the token
token |> Accounts.get_api_token! |> Accounts.revoke_api_token!
Users.get_user_with_api_token(token, "test") # force registration of the token
token |> Users.get_api_token! |> Users.revoke_api_token!
upload = fixture(:upload, %{path: "1/asciicast.json"})
conn = post conn, api_asciicast_path(conn, :create), %{"asciicast" => upload}
assert response(conn, 401)

@ -1,5 +1,5 @@
defmodule Asciinema.AsciicastAnimationControllerTest do
use AsciinemaWeb.ConnCase
use Asciinema.ConnCase
test "shows GIF generation instructions", %{conn: conn} do
asciicast = fixture(:asciicast)

@ -1,5 +1,5 @@
defmodule Asciinema.AsciicastEmbedControllerTest do
use AsciinemaWeb.ConnCase
use Asciinema.ConnCase
test "serves embed js", %{conn: conn} do
conn = get conn, "/a/12345.js"

@ -1,5 +1,5 @@
defmodule Asciinema.AsciicastFileControllerTest do
use AsciinemaWeb.ConnCase
use Asciinema.ConnCase
test "renders asciicast file", %{conn: conn} do
asciicast = fixture(:asciicast)

@ -1,5 +1,5 @@
defmodule Asciinema.AsciicastImageControllerTest do
use AsciinemaWeb.ConnCase
use Asciinema.ConnCase
@tag :a2png

@ -1,5 +1,5 @@
defmodule Asciinema.DocControllerTest do
use AsciinemaWeb.ConnCase
use Asciinema.ConnCase
test "GET /docs", %{conn: conn} do
conn = get conn, "/docs"

@ -1,5 +1,5 @@
defmodule Asciinema.LoginControllerTest do
use AsciinemaWeb.ConnCase
use Asciinema.ConnCase
test "with valid email", %{conn: conn} do
conn = post conn, "/login", %{login: %{email: "new@example.com"}}

@ -1,7 +1,6 @@
defmodule Asciinema.SessionControllerTest do
use AsciinemaWeb.ConnCase
alias Asciinema.Accounts
alias Asciinema.Accounts.{User, ApiToken}
use Asciinema.ConnCase
alias Asciinema.{Users, User, ApiToken}
@revoked_token "eb927b31-9ca3-4a6a-8a0c-dfba318e2e84"
@regular_user_token "c4ecd96a-9a16-464d-be6a-bc1f3c50c4ae"
@ -10,8 +9,8 @@ defmodule Asciinema.SessionControllerTest do
@other_tmp_user_token "2eafaa20-80c8-47fc-b014-74072027edae"
setup %{conn: conn} do
{:ok, %User{}} = Accounts.get_user_with_api_token(@revoked_token, "revoked")
@revoked_token |> Accounts.get_api_token! |> Accounts.revoke_api_token!
{:ok, %User{}} = Users.get_user_with_api_token(@revoked_token, "revoked")
@revoked_token |> Users.get_api_token! |> Users.revoke_api_token!
regular_user = fixture(:user)
ApiToken.create_changeset(regular_user, @regular_user_token) |> Repo.insert!
@ -19,9 +18,9 @@ defmodule Asciinema.SessionControllerTest do
other_regular_user = fixture(:user, %{username: "other", email: "other@example.com"})
ApiToken.create_changeset(other_regular_user, @other_regular_user_token) |> Repo.insert!
{:ok, %User{} = tmp_user} = Accounts.get_user_with_api_token(@tmp_user_token, "tmp")
{:ok, %User{} = tmp_user} = Users.get_user_with_api_token(@tmp_user_token, "tmp")
{:ok, %User{}} = Accounts.get_user_with_api_token(@other_tmp_user_token, "other_tmp")
{:ok, %User{}} = Users.get_user_with_api_token(@other_tmp_user_token, "other_tmp")
{:ok, conn: conn, regular_user: regular_user, tmp_user: tmp_user}
end

@ -0,0 +1,18 @@
defmodule Asciinema.UserTest do
use Asciinema.ModelCase
alias Asciinema.User
@valid_attrs %{email: "test@example.com"}
@invalid_attrs %{}
test "signup changeset with valid attributes" do
changeset = User.signup_changeset(@valid_attrs)
assert changeset.valid?
end
test "signup changeset with invalid attributes" do
changeset = User.signup_changeset(@invalid_attrs)
refute changeset.valid?
end
end

@ -1,4 +1,4 @@
defmodule AsciinemaWeb.ChannelCase do
defmodule Asciinema.ChannelCase do
@moduledoc """
This module defines the test case to be used by
channel tests.
@ -27,7 +27,7 @@ defmodule AsciinemaWeb.ChannelCase do
# The default endpoint for testing
@endpoint AsciinemaWeb.Endpoint
@endpoint Asciinema.Endpoint
end
end

@ -1,4 +1,4 @@
defmodule AsciinemaWeb.ConnCase do
defmodule Asciinema.ConnCase do
@moduledoc """
This module defines the test case to be used by
tests that require setting up a connection.
@ -25,12 +25,12 @@ defmodule AsciinemaWeb.ConnCase do
import Ecto.Changeset
import Ecto.Query
import AsciinemaWeb.Router.Helpers
import AsciinemaWeb.Router.Helpers.Extra
import Asciinema.Router.Helpers
import Asciinema.Router.Helpers.Extra
import Asciinema.Fixtures
# The default endpoint for testing
@endpoint AsciinemaWeb.Endpoint
@endpoint Asciinema.Endpoint
end
end

@ -1,6 +1,5 @@
defmodule Asciinema.Fixtures do
alias Asciinema.{Repo, Asciicasts}
alias Asciinema.Accounts.User
alias Asciinema.{Repo, Asciicasts, User}
def fixture(what, attrs \\ %{})

@ -0,0 +1,65 @@
defmodule Asciinema.ModelCase do
@moduledoc """
This module defines the test case to be used by
model tests.
You may define functions here to be used as helpers in
your model tests. See `errors_on/2`'s definition as reference.
Finally, if the test case interacts with the database,
it cannot be async. For this reason, every test runs
inside a transaction which is reset at the beginning
of the test unless the test case is marked as async.
"""
use ExUnit.CaseTemplate
using do
quote do
alias Asciinema.Repo
import Ecto
import Ecto.Changeset
import Ecto.Query
import Asciinema.ModelCase
end
end
setup tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(Asciinema.Repo)
unless tags[:async] do
Ecto.Adapters.SQL.Sandbox.mode(Asciinema.Repo, {:shared, self()})
end
:ok
end
@doc """
Helper for returning list of errors in a struct when given certain data.
## Examples
Given a User schema that lists `:name` as a required field and validates
`:password` to be safe, it would return:
iex> errors_on(%User{}, %{password: "password"})
[password: "is unsafe", name: "is blank"]
You could then write your assertion like:
assert {:password, "is unsafe"} in errors_on(%User{}, %{password: "password"})
You can also create the changeset manually and retrieve the errors
field directly:
iex> changeset = User.changeset(%User{}, password: "password")
iex> {:password, "is unsafe"} in changeset.errors
true
"""
def errors_on(struct, data) do
struct.__struct__.changeset(struct, data)
|> Ecto.Changeset.traverse_errors(&Asciinema.ErrorHelpers.translate_error/1)
|> Enum.flat_map(fn {key, errors} -> for msg <- errors, do: {key, msg} end)
end
end

@ -1,21 +1,21 @@
defmodule Asciinema.ErrorViewTest do
use AsciinemaWeb.ConnCase, async: true
use Asciinema.ConnCase, async: true
# Bring render/3 and render_to_string/3 for testing custom views
import Phoenix.View
test "renders 404.html" do
assert render_to_string(AsciinemaWeb.ErrorView, "404.html", []) =~
assert render_to_string(Asciinema.ErrorView, "404.html", []) =~
"not found"
end
test "render 500.html" do
assert render_to_string(AsciinemaWeb.ErrorView, "500.html", []) ==
assert render_to_string(Asciinema.ErrorView, "500.html", []) ==
"Internal server error"
end
test "render any other" do
assert render_to_string(AsciinemaWeb.ErrorView, "505.html", []) ==
assert render_to_string(Asciinema.ErrorView, "505.html", []) ==
"Internal server error"
end
end

@ -1,3 +1,3 @@
defmodule Asciinema.LayoutViewTest do
use AsciinemaWeb.ConnCase, async: true
use Asciinema.ConnCase, async: true
end

@ -1,3 +1,3 @@
defmodule Asciinema.PageViewTest do
use AsciinemaWeb.ConnCase, async: true
use Asciinema.ConnCase, async: true
end

@ -1,4 +1,4 @@
defmodule AsciinemaWeb.UserSocket do
defmodule Asciinema.UserSocket do
use Phoenix.Socket
## Channels
@ -30,7 +30,7 @@ defmodule AsciinemaWeb.UserSocket do
# Would allow you to broadcast a "disconnect" event and terminate
# all active sockets and channels for a given user:
#
# AsciinemaWeb.Endpoint.broadcast("users_socket:#{user.id}", "disconnect", %{})
# Asciinema.Endpoint.broadcast("users_socket:#{user.id}", "disconnect", %{})
#
# Returning `nil` makes this socket anonymous.
def id(_socket), do: nil

@ -1,8 +1,7 @@
defmodule AsciinemaWeb.Api.AsciicastController do
use AsciinemaWeb, :controller
import AsciinemaWeb.Auth, only: [get_basic_auth: 1, put_basic_auth: 3]
alias Asciinema.{Asciicasts, Accounts}
alias Asciinema.Accounts.User
defmodule Asciinema.Api.AsciicastController do
use Asciinema.Web, :controller
import Asciinema.Auth, only: [get_basic_auth: 1, put_basic_auth: 3]
alias Asciinema.{Asciicasts, Users, User}
plug :parse_v0_params
plug :authenticate
@ -62,7 +61,7 @@ defmodule AsciinemaWeb.Api.AsciicastController do
defp authenticate(conn, _opts) do
with {username, api_token} <- get_basic_auth(conn),
{:ok, %User{} = user} <- Accounts.get_user_with_api_token(api_token, username) do
{:ok, %User{} = user} <- Users.get_user_with_api_token(api_token, username) do
assign(conn, :current_user, user)
else
_otherwise ->

@ -1,5 +1,5 @@
defmodule AsciinemaWeb.AsciicastAnimationController do
use AsciinemaWeb, :controller
defmodule Asciinema.AsciicastAnimationController do
use Asciinema.Web, :controller
alias Asciinema.Asciicasts
def show(conn, %{"id" => id}) do

@ -1,5 +1,5 @@
defmodule AsciinemaWeb.AsciicastEmbedController do
use AsciinemaWeb, :controller
defmodule Asciinema.AsciicastEmbedController do
use Asciinema.Web, :controller
@max_age 60

@ -1,7 +1,6 @@
defmodule AsciinemaWeb.AsciicastFileController do
use AsciinemaWeb, :controller
alias Asciinema.Asciicasts
alias Asciinema.Asciicasts.Asciicast
defmodule Asciinema.AsciicastFileController do
use Asciinema.Web, :controller
alias Asciinema.{Asciicasts, Asciicast}
def show(conn, %{"id" => id} = params) do
asciicast = Asciicasts.get_asciicast!(id)

@ -1,9 +1,9 @@
defmodule AsciinemaWeb.AsciicastImageController do
use AsciinemaWeb, :controller
alias Asciinema.{Asciicasts, PngGenerator}
alias Asciinema.Asciicasts.Asciicast
defmodule Asciinema.AsciicastImageController do
use Asciinema.Web, :controller
alias Asciinema.{Asciicasts, Asciicast, PngGenerator}
alias Plug.MIME
@max_age 604_800 # 7 days
@max_age 604800 # 7 days
def show(conn, %{"id" => id} = _params) do
asciicast = Asciicasts.get_asciicast!(id)
@ -13,7 +13,7 @@ defmodule AsciinemaWeb.AsciicastImageController do
case PngGenerator.generate(asciicast, png_params) do
{:ok, png_path} ->
conn
|> put_resp_header("content-type", MIME.from_path(png_path))
|> put_resp_header("content-type", MIME.path(png_path))
|> put_resp_header("cache-control", "public, max-age=#{@max_age}")
|> send_file(200, png_path)
|> halt

@ -1,6 +1,6 @@
defmodule AsciinemaWeb.DocController do
use AsciinemaWeb, :controller
alias AsciinemaWeb.{DocView, ErrorView}
defmodule Asciinema.DocController do
use Asciinema.Web, :controller
alias Asciinema.{DocView, ErrorView}
@topics ["how-it-works", "getting-started", "installation", "usage", "config", "embedding", "faq"]

@ -1,6 +1,6 @@
defmodule AsciinemaWeb.LoginController do
use AsciinemaWeb, :controller
alias Asciinema.Accounts
defmodule Asciinema.LoginController do
use Asciinema.Web, :controller
alias Asciinema.Users
def new(conn, _params) do
render(conn, "new.html")
@ -9,7 +9,7 @@ defmodule AsciinemaWeb.LoginController do
def create(conn, %{"login" => %{"email" => email_or_username}}) do
email_or_username = String.trim(email_or_username)
case Accounts.send_login_email(email_or_username) do
case Users.send_login_email(email_or_username) do
{:ok, _url} ->
redirect(conn, to: login_path(conn, :sent))
{:error, :user_not_found} ->

@ -1,9 +1,7 @@
defmodule AsciinemaWeb.SessionController do
use AsciinemaWeb, :controller
import AsciinemaWeb.UserView, only: [profile_path: 1]
alias Asciinema.Accounts
alias AsciinemaWeb.Auth
alias Asciinema.Accounts.User
defmodule Asciinema.SessionController do
use Asciinema.Web, :controller
import Asciinema.UserView, only: [profile_path: 1]
alias Asciinema.{Users, User}
def new(conn, %{"t" => login_token}) do
conn
@ -15,7 +13,7 @@ defmodule AsciinemaWeb.SessionController do
end
def create(conn, %{"api_token" => api_token}) do
case Accounts.get_user_with_api_token(api_token) do
case Users.get_user_with_api_token(api_token) do
{:ok, user} ->
login_via_api_token(conn, user)
{:error, :token_invalid} ->
@ -33,10 +31,10 @@ defmodule AsciinemaWeb.SessionController do
login_token = get_session(conn, :login_token)
conn = delete_session(conn, :login_token)
case Accounts.verify_login_token(login_token) do
case Users.verify_login_token(login_token) do
{:ok, user} ->
conn
|> Auth.log_in(user)
|> Users.log_in(user)
|> put_rails_flash(:notice, "Welcome back!")
|> redirect_to_profile
{:error, :token_invalid} ->
@ -60,12 +58,12 @@ defmodule AsciinemaWeb.SessionController do
case {current_user, logging_user} do
{nil, %User{email: nil}} ->
conn
|> Auth.log_in(logging_user)
|> Users.log_in(logging_user)
|> put_rails_flash(:notice, "Welcome! Setting username and email will help you with logging in later.")
|> redirect_to_edit_profile
{nil, %User{}} ->
conn
|> Auth.log_in(logging_user)
|> Users.log_in(logging_user)
|> put_rails_flash(:notice, "Welcome back!")
|> redirect_to_profile
{%User{id: id, email: nil}, %User{id: id}} ->
@ -73,18 +71,18 @@ defmodule AsciinemaWeb.SessionController do
|> put_rails_flash(:notice, "Setting username and email will help you with logging in later.")
|> redirect_to_edit_profile
{%User{email: nil}, %User{email: nil}} ->
Accounts.merge!(current_user, logging_user)
Users.merge!(current_user, logging_user)
conn
|> put_rails_flash(:notice, "Setting username and email will help you with logging in later.")
|> redirect_to_edit_profile
{%User{email: nil}, %User{}} ->
Accounts.merge!(logging_user, current_user)
Users.merge!(logging_user, current_user)
conn
|> Auth.log_in(logging_user)
|> Users.log_in(logging_user)
|> put_rails_flash(:notice, "Recorder token has been added to your account.")
|> redirect_to_profile
{%User{}, %User{email: nil}} ->
Accounts.merge!(current_user, logging_user)
Users.merge!(current_user, logging_user)
conn
|> put_rails_flash(:notice, "Recorder token has been added to your account.")
|> redirect_to_profile

@ -1,7 +1,6 @@
defmodule AsciinemaWeb.UserController do
use AsciinemaWeb, :controller
alias Asciinema.Accounts
alias AsciinemaWeb.Auth
defmodule Asciinema.UserController do
use Asciinema.Web, :controller
alias Asciinema.Users
def new(conn, %{"t" => signup_token}) do
conn
@ -16,10 +15,10 @@ defmodule AsciinemaWeb.UserController do
signup_token = get_session(conn, :signup_token)
conn = delete_session(conn, :signup_token)
case Accounts.verify_signup_token(signup_token) do
case Users.verify_signup_token(signup_token) do
{:ok, user} ->
conn
|> Auth.log_in(user)
|> Users.log_in(user)
|> put_rails_flash(:info, "Welcome to asciinema!")
|> redirect(to: "/username/new")
{:error, :token_invalid} ->

@ -1,4 +1,4 @@
defmodule AsciinemaWeb.Gettext do
defmodule Asciinema.Gettext do
@moduledoc """
A module providing Internationalization with a gettext-based API.

@ -1,7 +1,6 @@
defmodule Asciinema.Accounts.ApiToken do
use Ecto.Schema
import Ecto.Changeset
alias Asciinema.Accounts.{ApiToken, User}
defmodule Asciinema.ApiToken do
use Asciinema.Web, :model
alias Asciinema.{ApiToken, User}
schema "api_tokens" do
field :token, :string
@ -9,7 +8,7 @@ defmodule Asciinema.Accounts.ApiToken do
timestamps(inserted_at: :created_at)
belongs_to :user, User
belongs_to :user, Asciinema.User
end
@uuid4 ~r/\A[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\z/

@ -1,8 +1,6 @@
defmodule Asciinema.Asciicasts.Asciicast do
use Ecto.Schema
import Ecto.Changeset
alias Asciinema.Accounts.User
alias Asciinema.Asciicasts.Asciicast
defmodule Asciinema.Asciicast do
use Asciinema.Web, :model
alias Asciinema.{User, Asciicast}
alias Asciinema.PngGenerator.PngParams
@default_png_scale 2

@ -1,7 +1,6 @@
defmodule Asciinema.Accounts.User do
use Ecto.Schema
import Ecto.Changeset
alias Asciinema.Accounts.User
defmodule Asciinema.User do
use Asciinema.Web, :model
alias Asciinema.User
@valid_email_re ~r/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i
@ -17,8 +16,8 @@ defmodule Asciinema.Accounts.User do
timestamps(inserted_at: :created_at)
has_many :asciicasts, Asciinema.Asciicasts.Asciicast
has_many :api_tokens, Asciinema.Accounts.ApiToken
has_many :asciicasts, Asciinema.Asciicast
has_many :api_tokens, Asciinema.ApiToken
end
def changeset(struct, params \\ %{}) do
@ -38,7 +37,6 @@ defmodule Asciinema.Accounts.User do
|> create_changeset(attrs)
|> cast(attrs, [:email])
|> validate_required([:email])
|> unique_constraint(:email, name: "index_users_on_email")
end
def login_changeset(user) do

@ -1,5 +1,5 @@
defmodule AsciinemaWeb.Router do
use AsciinemaWeb, :router
defmodule Asciinema.Router do
use Asciinema.Web, :router
pipeline :browser do
plug :accepts, ["html"]
@ -7,14 +7,14 @@ defmodule AsciinemaWeb.Router do
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
plug AsciinemaWeb.Auth
plug Asciinema.Auth
end
pipeline :asciicast_embed_script do
plug :accepts, ["js"]
end
scope "/", AsciinemaWeb do
scope "/", Asciinema do
pipe_through :asciicast_embed_script
# rewritten by TrailingFormat from /a/123.js to /a/123/js
@ -25,7 +25,7 @@ defmodule AsciinemaWeb.Router do
plug :accepts, ["json"]
end
scope "/", AsciinemaWeb do
scope "/", Asciinema do
pipe_through :asciicast_file
# rewritten by TrailingFormat from /a/123.json to /a/123/json
@ -36,7 +36,7 @@ defmodule AsciinemaWeb.Router do
plug :accepts, ["png"]
end
scope "/", AsciinemaWeb do
scope "/", Asciinema do
pipe_through :asciicast_image
# rewritten by TrailingFormat from /a/123.png to /a/123/png
@ -47,14 +47,14 @@ defmodule AsciinemaWeb.Router do
plug :accepts, ["html"]
end
scope "/", AsciinemaWeb do
scope "/", Asciinema do
pipe_through :asciicast_animation
# rewritten by TrailingFormat from /a/123.gif to /a/123/gif
get "/a/:id/gif", AsciicastAnimationController, :show
end
scope "/", AsciinemaWeb do
scope "/", Asciinema do
pipe_through :browser # Use the default browser stack
get "/a/:id", AsciicastController, :show
@ -71,7 +71,7 @@ defmodule AsciinemaWeb.Router do
get "/connect/:api_token", SessionController, :create, as: :connect
end
scope "/api", AsciinemaWeb.Api, as: :api do
scope "/api", Asciinema.Api, as: :api do
post "/asciicasts", AsciicastController, :create
end
@ -81,34 +81,30 @@ defmodule AsciinemaWeb.Router do
# end
end
defmodule AsciinemaWeb.Router.Helpers.Extra do
alias AsciinemaWeb.Router.Helpers, as: H
defmodule Asciinema.Router.Helpers.Extra do
alias Asciinema.Router.Helpers, as: H
def user_path(_conn, :edit) do
"/user/edit"
end
def asciicast_file_download_path(conn, asciicast) do
conn
|> H.asciicast_file_path(:show, asciicast)
H.asciicast_file_path(conn, :show, asciicast)
|> String.replace_suffix("/json", ".json")
end
def asciicast_file_download_url(conn, asciicast) do
conn
|> H.asciicast_file_url(:show, asciicast)
H.asciicast_file_url(conn, :show, asciicast)
|> String.replace_suffix("/json", ".json")
end
def asciicast_image_download_path(conn, asciicast) do
conn
|> H.asciicast_image_path(:show, asciicast)
H.asciicast_image_path(conn, :show, asciicast)
|> String.replace_suffix("/png", ".png")
end
def asciicast_animation_download_path(conn, asciicast) do
conn
|> H.asciicast_animation_path(:show, asciicast)
H.asciicast_animation_path(conn, :show, asciicast)
|> String.replace_suffix("/gif", ".gif")
end
end

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Before

Width:  |  Height:  |  Size: 768 B

After

Width:  |  Height:  |  Size: 768 B

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 188 KiB

Before

Width:  |  Height:  |  Size: 731 B

After

Width:  |  Height:  |  Size: 731 B

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save