Skip to content

Commit e51c583

Browse files
fix: build failed with unreplaced title variables (wraft#182)
* fix: build fail with unreplaced title variables * fix(auth): handle missing token error * feat: add query by name in instance approval indexing * fix: safely handle nil document titles * chore: update version to 0.6.5 and display it on the index page --------- Co-authored-by: Salsabeel <[email protected]>
1 parent e389ea7 commit e51c583

9 files changed

Lines changed: 144 additions & 29 deletions

File tree

lib/wraft_doc/documents/documents.ex

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,14 +1341,14 @@ defmodule WraftDoc.Documents do
13411341
task
13421342
) do
13431343
qr_code = Task.await(task)
1344-
page_title = instance.serialized["title"]
1344+
page_title = format_title(instance.serialized["title"])
13451345

13461346
header =
13471347
header
13481348
|> Assets.find_asset_header_values(layout, instance)
13491349
|> concat_strings("qrcode: #{qr_code} \n")
13501350
|> concat_strings("path: #{mkdir}\n")
1351-
|> concat_strings("title: #{page_title}\n")
1351+
|> concat_strings("title: \"#{page_title}\"\n")
13521352
|> concat_strings("organisation_name: #{organisation_name}\n")
13531353
|> concat_strings("author_name: #{name}\n")
13541354
|> concat_strings("author_email: #{email}\n")
@@ -1388,6 +1388,16 @@ defmodule WraftDoc.Documents do
13881388
"""
13891389
end
13901390

1391+
defp format_title(nil), do: ""
1392+
1393+
defp format_title(title) when is_binary(title) do
1394+
title
1395+
|> String.replace("[", "\[")
1396+
|> String.replace("]", "\]")
1397+
end
1398+
1399+
defp format_title(title), do: to_string(title)
1400+
13911401
defp add_margin(header, nil), do: header
13921402

13931403
defp add_margin(header, %{top: top, bottom: bottom, left: left, right: right}),
@@ -2184,7 +2194,10 @@ defmodule WraftDoc.Documents do
21842194
Repo.paginate(query, params)
21852195
end
21862196

2187-
def list_pending_approvals(%User{id: user_id, current_org_id: org_id} = _current_user, params) do
2197+
def list_pending_approvals(
2198+
%User{id: user_id, current_org_id: org_id} = _current_user,
2199+
params
2200+
) do
21882201
next_state_query =
21892202
from(s in State,
21902203
where:
@@ -2201,6 +2214,7 @@ defmodule WraftDoc.Documents do
22012214

22022215
Instance
22032216
|> where([i], i.approval_status == false)
2217+
|> maybe_filter_by_title(params)
22042218
|> join(:inner, [i], s in State,
22052219
on: s.id == i.state_id and s.organisation_id == ^org_id,
22062220
as: :state
@@ -2220,6 +2234,21 @@ defmodule WraftDoc.Documents do
22202234
|> Repo.paginate(params)
22212235
end
22222236

2237+
defp maybe_filter_by_title(query, %{"name" => name})
2238+
when is_binary(name) and name != "" do
2239+
where(
2240+
query,
2241+
[i],
2242+
fragment(
2243+
"LOWER(?->>'title') LIKE LOWER(?)",
2244+
i.serialized,
2245+
^"%#{name}%"
2246+
)
2247+
)
2248+
end
2249+
2250+
defp maybe_filter_by_title(query, _params), do: query
2251+
22232252
@doc """
22242253
Retrieves dashboard statistics for the current organization.
22252254

lib/wraft_doc_web/auth/auth_error_handler.ex

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
defmodule WraftDocWeb.Guardian.AuthErrorHandler do
22
@moduledoc """
3-
Error handler for Guradian.
3+
Error handler for Guardian.
44
"""
55
import Plug.Conn
66

77
def auth_error(conn, {:invalid_token, _reason}, _opts) do
8-
body = Jason.encode!(%{message: "Token is either expired or invalid. Login again."})
9-
conn |> put_resp_content_type("application/json") |> send_resp(401, body)
8+
body = Jason.encode!(%{errors: "Token is either expired or invalid. Login again."})
9+
conn |> put_resp_content_type("application/json") |> send_resp(401, body) |> halt()
10+
end
11+
12+
def auth_error(conn, {:unauthenticated, _reason}, _opts) do
13+
body = Jason.encode!(%{errors: "Unauthorized. Please provide valid authentication."})
14+
conn |> put_resp_content_type("application/json") |> send_resp(401, body) |> halt()
1015
end
1116

1217
def auth_error(conn, {type, _reason}, _opts) do
13-
body = Jason.encode!(%{message: to_string(type)})
14-
conn |> put_resp_content_type("application/json") |> send_resp(401, body)
18+
body = Jason.encode!(%{errors: to_string(type)})
19+
conn |> put_resp_content_type("application/json") |> send_resp(401, body) |> halt()
1520
end
1621

1722
def auth_error(conn, {:error, :no_user}) do

lib/wraft_doc_web/auth/current_organisation.ex

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,19 @@ defmodule WraftDocWeb.CurrentOrganisation do
3636
end
3737

3838
defp process_jwt_org(conn) do
39-
%{"organisation_id" => org_id} = current_claims(conn)
39+
case current_claims(conn) do
40+
nil ->
41+
conn
42+
43+
%{"organisation_id" => org_id} ->
44+
load_organisation_and_roles(conn, org_id)
45+
46+
_claims ->
47+
conn
48+
end
49+
end
4050

51+
defp load_organisation_and_roles(conn, org_id) do
4152
case Repo.get(Organisation, org_id) do
4253
nil ->
4354
AuthErrorHandler.auth_error(conn, {:error, :no_org})

lib/wraft_doc_web/auth/current_user.ex

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ defmodule WraftDocWeb.CurrentUser do
2727
end
2828

2929
defp maybe_add_auth_type(%{params: params} = conn) do
30-
conn
31-
|> current_claims()
32-
|> add_type_to_params(conn, params)
30+
case current_claims(conn) do
31+
nil -> conn
32+
claims -> add_type_to_params(claims, conn, params)
33+
end
3334
end
3435

3536
defp add_type_to_params(%{"type" => type}, conn, params),
@@ -39,16 +40,15 @@ defmodule WraftDocWeb.CurrentUser do
3940
do: conn
4041

4142
defp add_current_user(conn) do
42-
conn
43-
|> current_resource()
44-
|> case do
45-
nil -> AuthErrorHandler.auth_error(conn, {:error, :no_user})
46-
email -> get_user(email)
47-
end
48-
|> case do
49-
%Plug.Conn{} = conn -> conn
50-
nil -> AuthErrorHandler.auth_error(conn, {:error, :no_user})
51-
user -> assign(conn, :current_user, preload_user_data(user))
43+
case current_resource(conn) do
44+
nil ->
45+
conn
46+
47+
email ->
48+
case get_user(email) do
49+
nil -> AuthErrorHandler.auth_error(conn, {:error, :no_user})
50+
user -> assign(conn, :current_user, preload_user_data(user))
51+
end
5252
end
5353
end
5454

lib/wraft_doc_web/controllers/page_controller.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ defmodule WraftDocWeb.PageController do
22
use WraftDocWeb, :controller
33

44
def index(conn, _params) do
5-
render(conn, "index.html")
5+
version = Application.spec(:wraft_doc, :vsn) |> to_string()
6+
render(conn, "index.html", version: version)
67
end
78
end

lib/wraft_doc_web/templates/page/index.html.heex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
</div>
8181
<h1>Wraft</h1>
8282
<p>> Wraft is an open-source document lifecycle management software</p>
83+
<p style="margin-top: 1rem; font-size: 0.9rem; opacity: 0.8;">Version: <%= @version %></p>
8384
</div>
8485
</body>
8586
</html>

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ defmodule WraftDoc.Mixfile do
55
def project do
66
[
77
app: :wraft_doc,
8-
version: "0.6.4",
8+
version: "0.6.5",
99
elixir: "~> 1.18",
1010
elixirc_paths: elixirc_paths(Mix.env()),
1111
compilers: Mix.compilers(),

test/wraft_doc_web/auth/current_organisation_test.exs

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,11 @@ defmodule WraftDocWeb.Auth.CurrentOrganisationTest do
7373
|> CurrentOrganisation.call([])
7474

7575
assert conn.assigns[:current_user].current_org_id == user.current_org_id
76-
# Permissions should be unique and aggregated
7776
assert length(conn.assigns[:current_user].permissions) == 4
7877
assert "layout:index" in conn.assigns[:current_user].permissions
7978
assert "layout:show" in conn.assigns[:current_user].permissions
8079
assert "layout:create" in conn.assigns[:current_user].permissions
8180
assert "layout:update" in conn.assigns[:current_user].permissions
82-
# Role names should include both roles
8381
assert length(conn.assigns[:current_user].role_names) == 2
8482
assert role1.name in conn.assigns[:current_user].role_names
8583
assert role2.name in conn.assigns[:current_user].role_names
@@ -126,7 +124,6 @@ defmodule WraftDocWeb.Auth.CurrentOrganisationTest do
126124
{:ok, token, _claims} =
127125
Guardian.encode_and_sign(user, %{organisation_id: user.current_org_id})
128126

129-
# Pre-assign user with org_id
130127
user_with_org = Map.put(user, :current_org_id, organisation.id)
131128

132129
conn =
@@ -135,7 +132,6 @@ defmodule WraftDocWeb.Auth.CurrentOrganisationTest do
135132
|> assign(:current_user, user_with_org)
136133
|> CurrentOrganisation.call([])
137134

138-
# Should keep the existing org_id and not process JWT
139135
assert conn.assigns[:current_user].current_org_id == organisation.id
140136
refute conn.halted
141137
end
@@ -187,14 +183,60 @@ defmodule WraftDocWeb.Auth.CurrentOrganisationTest do
187183
|> conn_init()
188184
|> CurrentOrganisation.call([])
189185

190-
# Should only have role from organisation1
191186
assert conn.assigns[:current_user].current_org_id == organisation1.id
192187
assert conn.assigns[:current_user].role_names == [role1.name]
193188
assert conn.assigns[:current_user].permissions == ["layout:index"]
194189
refute role2.name in conn.assigns[:current_user].role_names
195190
refute "layout:show" in conn.assigns[:current_user].permissions
196191
refute conn.halted
197192
end
193+
194+
test "does not halt when no JWT token is provided" do
195+
conn =
196+
build_conn()
197+
|> put_req_header("content-type", "application/json")
198+
|> put_resp_content_type("application/json")
199+
|> Map.put(:params, %{})
200+
|> CurrentOrganisation.call([])
201+
202+
refute conn.halted
203+
end
204+
205+
test "does not halt when claims are nil" do
206+
conn =
207+
build_conn()
208+
|> put_req_header("content-type", "application/json")
209+
|> put_resp_content_type("application/json")
210+
|> Map.put(:params, %{})
211+
|> Plug.put_current_claims(nil)
212+
|> CurrentOrganisation.call([])
213+
214+
refute conn.halted
215+
end
216+
217+
test "does not halt when claims don't have organisation_id" do
218+
user = insert(:user_with_organisation)
219+
220+
{:ok, token, _claims} =
221+
Guardian.encode_and_sign(user, %{some_other_key: "value"})
222+
223+
conn =
224+
build_conn()
225+
|> put_req_header("authorization", "Bearer " <> token)
226+
|> put_resp_content_type("application/json")
227+
|> Map.put(:params, %{})
228+
|> then(fn conn ->
229+
{:ok, claims} = Guardian.decode_and_verify(token)
230+
231+
conn
232+
|> Plug.put_current_claims(claims)
233+
|> Plug.put_current_resource(claims["sub"])
234+
|> CurrentUser.call([])
235+
end)
236+
|> CurrentOrganisation.call([])
237+
238+
refute conn.halted
239+
end
198240
end
199241

200242
# Private

test/wraft_doc_web/auth/current_user_test.exs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,32 @@ defmodule WraftDocWeb.Auth.CurrentUserTest do
111111
assert conn.assigns[:current_user].id == user.id
112112
refute conn.halted
113113
end
114+
115+
test "does not halt when no JWT token is provided" do
116+
conn =
117+
build_conn()
118+
|> put_req_header("content-type", "application/json")
119+
|> put_resp_content_type("application/json")
120+
|> Map.put(:params, %{})
121+
|> CurrentUser.call([])
122+
123+
refute Map.has_key?(conn.assigns, :current_user)
124+
refute conn.halted
125+
end
126+
127+
test "does not halt when claims are nil" do
128+
conn =
129+
build_conn()
130+
|> put_req_header("content-type", "application/json")
131+
|> put_resp_content_type("application/json")
132+
|> Map.put(:params, %{})
133+
|> Plug.put_current_claims(nil)
134+
|> Plug.put_current_resource(nil)
135+
|> CurrentUser.call([])
136+
137+
refute Map.has_key?(conn.assigns, :current_user)
138+
refute conn.halted
139+
end
114140
end
115141

116142
# Private

0 commit comments

Comments
 (0)