Skip to content

Commit db687a8

Browse files
committed
Add DEFAULT_RECORDING_VISIBILITY and DEFAULT_STREAM_VISIBILITY config options
1 parent 5e2d905 commit db687a8

File tree

11 files changed

+151
-52
lines changed

11 files changed

+151
-52
lines changed

config/runtime.exs

+13
Original file line numberDiff line numberDiff line change
@@ -252,4 +252,17 @@ if config_env() in [:prod, :dev] do
252252
if email = env.("CONTACT_EMAIL_ADDRESS") do
253253
config :asciinema, contact_email_address: email
254254
end
255+
256+
visibility = env.("DEFAULT_RECORDING_VISIBILITY")
257+
258+
if visibility in ~w[private unlisted public] do
259+
config :asciinema, Asciinema.Accounts,
260+
default_recording_visibility: String.to_atom(visibility)
261+
end
262+
263+
visibility = env.("DEFAULT_STREAM_VISIBILITY")
264+
265+
if visibility in ~w[private unlisted public] do
266+
config :asciinema, Asciinema.Accounts, default_stream_visibility: String.to_atom(visibility)
267+
end
255268
end

lib/asciinema.ex

+16-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
defmodule Asciinema do
22
alias Asciinema.{Accounts, Emails, Recordings, Repo, Streaming}
33

4-
def create_user_from_email(email) do
5-
with {:ok, user} <- Accounts.create_user_from_email(email) do
4+
def create_user(attrs) do
5+
with {:ok, user} <- Accounts.create_user(attrs) do
66
if Streaming.mode() == :static do
77
Streaming.create_stream!(user)
88
end
@@ -11,6 +11,19 @@ defmodule Asciinema do
1111
end
1212
end
1313

14+
def create_user_from_sign_up_token(token) do
15+
with {:ok, email} <- Accounts.verify_sign_up_token(token),
16+
{:ok, user} <- create_user(%{email: email}) do
17+
{:ok, user}
18+
else
19+
{:error, %Ecto.Changeset{errors: [{:email, _}]}} ->
20+
{:error, :email_taken}
21+
22+
result ->
23+
result
24+
end
25+
end
26+
1427
defdelegate change_user(user, params \\ %{}), to: Accounts
1528

1629
def update_user(user, params) do
@@ -21,12 +34,6 @@ defmodule Asciinema do
2134
end
2235
end
2336

24-
def create_user_from_sign_up_token(token) do
25-
with {:ok, email} <- Accounts.verify_sign_up_token(token) do
26-
create_user_from_email(email)
27-
end
28-
end
29-
3037
def send_login_email(identifier, url_provider, opts \\ []) do
3138
case Accounts.generate_login_token(identifier, opts) do
3239
{:ok, {type, token, email}} ->
@@ -43,6 +50,7 @@ defmodule Asciinema do
4350
Emails.send_email(:account_deletion, user.email, token, url_provider)
4451
end
4552

53+
defdelegate generate_login_token(email), to: Accounts
4654
defdelegate verify_login_token(token), to: Accounts
4755

4856
def register_cli(user, token) do

lib/asciinema/accounts.ex

+27-27
Original file line numberDiff line numberDiff line change
@@ -47,35 +47,29 @@ defmodule Asciinema.Accounts do
4747
Repo.all(from(u in User, order_by: [asc: :id], limit: ^limit))
4848
end
4949

50+
def build_user(attrs \\ %{}) do
51+
Changeset.change(
52+
%User{
53+
default_recording_visibility: config(:default_recording_visibility, :unlisted),
54+
default_stream_visibility: config(:default_stream_visibility, :unlisted)
55+
},
56+
attrs
57+
)
58+
end
59+
5060
def create_user(attrs) do
5161
import Ecto.Changeset
5262

53-
%User{}
63+
build_user()
5464
|> cast(attrs, [:email, :username])
5565
|> validate_required([:email])
5666
|> update_change(:email, &String.downcase/1)
5767
|> validate_format(:email, @valid_email_re)
68+
|> validate_username()
5869
|> add_contraints()
5970
|> Repo.insert()
6071
end
6172

62-
def create_user_from_email(email) do
63-
import Ecto.Changeset
64-
65-
result =
66-
%User{}
67-
|> cast(%{email: email}, [:email])
68-
|> validate_required([:email])
69-
|> update_change(:email, &String.downcase/1)
70-
|> validate_format(:email, @valid_email_re)
71-
|> add_contraints()
72-
|> Repo.insert()
73-
74-
with {:error, %Ecto.Changeset{errors: [{:email, _}]}} <- result do
75-
{:error, :email_taken}
76-
end
77-
end
78-
7973
def ensure_asciinema_user do
8074
case Repo.get_by(User, username: "asciinema") do
8175
nil ->
@@ -85,17 +79,15 @@ defmodule Asciinema.Accounts do
8579
8680
}
8781

88-
%User{}
89-
|> change_user(attrs)
82+
attrs
83+
|> build_user()
9084
|> Repo.insert!()
9185

9286
user ->
9387
user
9488
end
9589
end
9690

97-
def new_user, do: change_user(%User{})
98-
9991
def change_user(user, params \\ %{}) do
10092
import Ecto.Changeset
10193

@@ -108,18 +100,26 @@ defmodule Asciinema.Accounts do
108100
:theme_prefer_original,
109101
:terminal_font_family,
110102
:default_recording_visibility,
103+
:default_stream_visibility,
111104
:stream_recording_enabled
112105
])
113106
|> validate_required([:email])
114107
|> update_change(:email, &String.downcase/1)
115108
|> validate_format(:email, @valid_email_re)
116-
|> validate_format(:username, @valid_username_re)
117-
|> validate_length(:username, min: 2, max: 16)
109+
|> validate_username()
118110
|> validate_inclusion(:theme_name, Themes.terminal_themes())
119111
|> validate_inclusion(:terminal_font_family, Fonts.terminal_font_families())
120112
|> add_contraints()
121113
end
122114

115+
defp validate_username(changeset) do
116+
import Ecto.Changeset
117+
118+
changeset
119+
|> validate_format(:username, @valid_username_re)
120+
|> validate_length(:username, min: 2, max: 16)
121+
end
122+
123123
defp add_contraints(changeset) do
124124
import Ecto.Changeset
125125

@@ -298,9 +298,9 @@ defmodule Asciinema.Accounts do
298298
end
299299

300300
defp create_tmp_user(username) do
301-
username = String.slice(username, 0, 16)
302-
303-
Repo.insert!(%User{temporary_username: username})
301+
%{temporary_username: String.slice(username, 0, 16)}
302+
|> build_user()
303+
|> Repo.insert!()
304304
end
305305

306306
defp check_cli_ownership(user, cli) do

lib/asciinema/accounts/user.ex

+2-5
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,8 @@ defmodule Asciinema.Accounts.User do
1414
field :terminal_font_family, :string
1515
field :streaming_enabled, :boolean, default: true
1616
field :stream_recording_enabled, :boolean, default: true
17-
18-
field :default_recording_visibility, Ecto.Enum,
19-
values: ~w[private unlisted public]a,
20-
default: :unlisted
21-
17+
field :default_recording_visibility, Ecto.Enum, values: ~w[private unlisted public]a
18+
field :default_stream_visibility, Ecto.Enum, values: ~w[private unlisted public]a
2219
field :last_login_at, :utc_datetime_usec
2320
field :is_admin, :boolean
2421

lib/asciinema/streaming.ex

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ defmodule Asciinema.Streaming do
9191
|> change(
9292
public_token: generate_public_token(),
9393
producer_token: generate_producer_token(),
94+
visibility: user.default_stream_visibility,
9495
theme_prefer_original: user.theme_prefer_original
9596
)
9697
|> put_assoc(:user, user)

lib/asciinema_admin/controllers/user_controller.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ defmodule AsciinemaAdmin.UserController do
1010
end
1111

1212
def new(conn, _params) do
13-
render(conn, :new, changeset: Accounts.new_user())
13+
render(conn, :new, changeset: Accounts.build_user())
1414
end
1515

1616
def create(conn, %{"user" => attrs}) do
17-
case Accounts.create_user(attrs) do
17+
case Asciinema.create_user(attrs) do
1818
{:ok, user} ->
1919
redirect(conn, to: ~p"/admin/users/#{user}")
2020

lib/asciinema_web/controllers/user_controller.ex

+1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ defmodule AsciinemaWeb.UserController do
116116

117117
render(conn, "edit.html",
118118
changeset: changeset,
119+
streaming_mode: Streaming.mode(),
119120
stream_recording_mode: Streaming.recording_mode(),
120121
clis: clis
121122
)

lib/asciinema_web/controllers/user_html/edit.html.heex

+62-2
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@
8080
<legend>Defaults</legend>
8181

8282
<p>
83-
The settings below control the defaults for your uploaded recordings. <br />
83+
The settings below control the defaults for <strong>new</strong>
84+
recordings and streams. <br />
8485
<br />
8586
</p>
8687

@@ -138,7 +139,66 @@
138139
</small>
139140
</div>
140141
<small class="form-text text-muted">
141-
NOTE: This setting applies to *new* uploads. Existing recordings are not affected by changes to this setting.
142+
NOTE: Existing recordings are not affected by changes to this setting.
143+
</small>
144+
</div>
145+
</div>
146+
147+
<div :if={@streaming_mode == :dynamic} class="form-group row">
148+
<.label for={f[:default_stream_visibility]} class="col-3 col-form-label">
149+
Stream visibility
150+
</.label>
151+
<div class="col-9 visibility-radios">
152+
<div class="form-check">
153+
<input
154+
type="radio"
155+
name="user[default_stream_visibility]"
156+
id="user_default_stream_visibility_public"
157+
value="public"
158+
checked={f[:default_stream_visibility].value == :public}
159+
class="form-check-input"
160+
/>
161+
<label for="user_default_stream_visibility_public" class="form-check-label">
162+
Public
163+
</label>
164+
<small class="form-text text-muted">
165+
Anyone can view, listed on your public profile
166+
</small>
167+
</div>
168+
<div class="form-check">
169+
<input
170+
type="radio"
171+
name="user[default_stream_visibility]"
172+
id="user_default_stream_visibility_unlisted"
173+
value="unlisted"
174+
checked={f[:default_stream_visibility].value == :unlisted}
175+
class="form-check-input"
176+
/>
177+
<label for="user_default_stream_visibility_unlisted" class="form-check-label">
178+
Unlisted
179+
</label>
180+
<small class="form-text text-muted">
181+
Only people with the link can view
182+
</small>
183+
</div>
184+
<div class="form-check">
185+
<input
186+
type="radio"
187+
name="user[default_stream_visibility]"
188+
id="user_default_stream_visibility_private"
189+
value="private"
190+
checked={f[:default_stream_visibility].value == :private}
191+
class="form-check-input"
192+
/>
193+
<label for="user_default_stream_visibility_private" class="form-check-label">
194+
Private
195+
</label>
196+
<small class="form-text text-muted">
197+
Only accessible by you
198+
</small>
199+
</div>
200+
<small class="form-text text-muted">
201+
NOTE: Existing streams are not affected by changes to this setting.
142202
</small>
143203
</div>
144204
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
defmodule Asciinema.Repo.Migrations.AddDefaultStreamVisibilityToUsers do
2+
use Ecto.Migration
3+
4+
def change do
5+
alter table(:users) do
6+
add :default_stream_visibility, :stream_visibility, null: false, default: "unlisted"
7+
end
8+
end
9+
end

test/asciinema_test.exs

+15-7
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,29 @@ defmodule AsciinemaTest do
88
@urls Asciinema.TestUrlProvider
99

1010
describe "create_user/1" do
11-
test "succeeds when email not taken" do
12-
assert {:ok, _} = Asciinema.create_user_from_email("[email protected]")
13-
assert {:error, :email_taken} = Asciinema.create_user_from_email("[email protected]")
14-
assert {:error, :email_taken} = Asciinema.create_user_from_email("[email protected]")
11+
test "succeeds for valid attrs" do
12+
assert {:ok, _} = Asciinema.create_user(%{email: "[email protected]", username: "test"})
13+
end
14+
15+
test "fails for invalid attrs" do
16+
assert {:error, %Ecto.Changeset{}} =
17+
Asciinema.create_user(%{email: "[email protected]", username: "a"})
1518
end
1619
end
1720

1821
describe "create_user_from_sign_up_token/1" do
1922
test "succeeds when email not taken" do
20-
# TODO don't reach to Accounts
21-
{:ok, {:sign_up, token, _email}} =
22-
Asciinema.Accounts.generate_login_token("[email protected]")
23+
{:ok, {:sign_up, token, _email}} = Asciinema.generate_login_token("[email protected]")
2324

2425
assert {:ok, _} = Asciinema.create_user_from_sign_up_token(token)
2526
end
27+
28+
test "fails when email address taken" do
29+
{:ok, {:sign_up, token, _email}} = Asciinema.generate_login_token("[email protected]")
30+
insert(:user, email: "[email protected]")
31+
32+
assert Asciinema.create_user_from_sign_up_token(token) == {:error, :email_taken}
33+
end
2634
end
2735

2836
describe "send_login_email/3" do

test/support/factory.ex

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ defmodule Asciinema.Factory do
99
%User{
1010
username: sequence(:username, &"username-#{&1}"),
1111
email: sequence(:email, &"email-#{&1}@example.com"),
12-
auth_token: Crypto.random_token(20)
12+
auth_token: Crypto.random_token(20),
13+
default_recording_visibility: :unlisted,
14+
default_stream_visibility: :unlisted
1315
}
1416
end
1517

0 commit comments

Comments
 (0)