/__w/shurbej/shurbej/_build/test/cover/aggregate/shurbej_http_fulltext.html

1 -module(shurbej_http_fulltext).
2 -include_lib("shurbej_store/include/shurbej_records.hrl").
3
4 -export([init/2]).
5
6 init(Req0, State) ->
7 11 case shurbej_http_common:authorize(Req0) of
8 {ok, LibRef, _} ->
9 10 Method = cowboy_req:method(Req0),
10 10 Perm = perm_for_method(Method),
11 10 case shurbej_http_common:check_lib_perm(Perm, LibRef) of
12 {error, forbidden} ->
13
:-(
Req = shurbej_http_common:error_response(403, <<"Access denied">>, Req0),
14
:-(
{ok, Req, State};
15 ok ->
16 10 handle(Method, Req0, State)
17 end;
18 {error, Reason, _} ->
19 1 Req = shurbej_http_common:auth_error_response(Reason, Req0),
20 1 {ok, Req, State}
21 end.
22
23 6 perm_for_method(<<"GET">>) -> read;
24
:-(
perm_for_method(<<"HEAD">>) -> read;
25 4 perm_for_method(_) -> write.
26
27 %% GET /<lib>/fulltext — list versions of all full-text entries
28 handle(<<"GET">>, Req0, #{scope := versions} = State) ->
29 4 LibRef = shurbej_http_common:lib_ref(Req0),
30 4 {ok, LibVersion} = shurbej_version:get(LibRef),
31 4 case shurbej_http_common:check_304(Req0, LibVersion) of
32 1 {304, Req} -> {ok, Req, State};
33 continue ->
34 3 Since = shurbej_http_common:get_since(Req0),
35 3 Pairs = shurbej_db:list_fulltext_versions(LibRef, Since),
36 3 Req = shurbej_http_common:json_response(200, maps:from_list(Pairs), LibVersion, Req0),
37 3 {ok, Req, State}
38 end;
39
40 %% GET /<lib>/items/:item_key/fulltext
41 handle(<<"GET">>, Req0, #{scope := single} = State) ->
42 2 LibRef = shurbej_http_common:lib_ref(Req0),
43 2 ItemKey = cowboy_req:binding(item_key, Req0),
44 2 case shurbej_db:get_fulltext(LibRef, ItemKey) of
45 {ok, #shurbej_fulltext{content = Content, version = Version,
46 indexed_pages = IP, total_pages = TP,
47 indexed_chars = IC, total_chars = TC}} ->
48 1 Body = #{
49 <<"content">> => Content,
50 <<"indexedPages">> => IP, <<"totalPages">> => TP,
51 <<"indexedChars">> => IC, <<"totalChars">> => TC
52 },
53 1 Req = shurbej_http_common:json_response(200, Body, Version, Req0),
54 1 {ok, Req, State};
55 undefined ->
56 1 Req = shurbej_http_common:error_response(404, <<"Full-text content not found">>, Req0),
57 1 {ok, Req, State}
58 end;
59
60 %% PUT /<lib>/items/:item_key/fulltext — with input validation
61 handle(<<"PUT">>, Req0, #{scope := single} = State) ->
62 3 {LT, LI} = LibRef = shurbej_http_common:lib_ref(Req0),
63 3 ItemKey = cowboy_req:binding(item_key, Req0),
64 3 ExpectedVersion = shurbej_http_common:get_if_unmodified(Req0),
65 3 case shurbej_http_common:read_json_body(Req0) of
66 {error, _, Req1} ->
67
:-(
Req = shurbej_http_common:error_response(400, <<"Invalid JSON">>, Req1),
68
:-(
{ok, Req, State};
69 {ok, Data, Req1} ->
70 3 case validate_fulltext(Data) of
71 {error, Reason} ->
72 1 Req = shurbej_http_common:error_response(400, Reason, Req1),
73 1 {ok, Req, State};
74 ok ->
75 2 Content = maps:get(<<"content">>, Data, <<>>),
76 2 case shurbej_version:write(LibRef, ExpectedVersion, fun(NewVersion) ->
77 2 shurbej_db:write_fulltext(#shurbej_fulltext{
78 id = {LT, LI, ItemKey},
79 version = NewVersion,
80 content = Content,
81 indexed_pages = to_int(maps:get(<<"indexedPages">>, Data, 0)),
82 total_pages = to_int(maps:get(<<"totalPages">>, Data, 0)),
83 indexed_chars = to_int(maps:get(<<"indexedChars">>, Data, 0)),
84 total_chars = to_int(maps:get(<<"totalChars">>, Data, 0))
85 }),
86 2 ok
87 end) of
88 {ok, NewVersion} ->
89 2 Req = cowboy_req:reply(204, #{
90 <<"last-modified-version">> => integer_to_binary(NewVersion)
91 }, Req1),
92 2 {ok, Req, State};
93 {error, precondition, CurrentVersion} ->
94
:-(
Req = shurbej_http_common:json_response(412,
95 #{<<"message">> => <<"Library has been modified since specified version">>},
96 CurrentVersion, Req1),
97
:-(
{ok, Req, State}
98 end
99 end
100 end;
101
102 handle(_, Req0, State) ->
103 1 Req = shurbej_http_common:error_response(405, <<"Method not allowed">>, Req0),
104 1 {ok, Req, State}.
105
106 validate_fulltext(Data) when is_map(Data) ->
107 3 case maps:get(<<"content">>, Data, undefined) of
108 1 undefined -> {error, <<"Missing required field: content">>};
109 2 C when is_binary(C) -> ok;
110
:-(
_ -> {error, <<"'content' must be a string">>}
111 end;
112 validate_fulltext(_) ->
113
:-(
{error, <<"Body must be a JSON object">>}.
114
115 8 to_int(V) when is_integer(V) -> V;
116
:-(
to_int(_) -> 0.
Line Hits Source