/__w/shurbej/shurbej/_build/test/cover/ct/shurbej_http_settings.html

1 -module(shurbej_http_settings).
2 -include_lib("shurbej_store/include/shurbej_records.hrl").
3
4 -export([init/2]).
5
6 init(Req0, State) ->
7 18 case shurbej_http_common:authorize(Req0) of
8 {ok, LibRef, _} ->
9 17 Method = cowboy_req:method(Req0),
10 17 Perm = perm_for_method(Method),
11 17 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 17 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 10 perm_for_method(<<"GET">>) -> read;
24
:-(
perm_for_method(<<"HEAD">>) -> read;
25 7 perm_for_method(_) -> write.
26
27 handle(<<"GET">>, Req0, #{scope := single} = State) ->
28 5 LibRef = shurbej_http_common:lib_ref(Req0),
29 5 SettingKey = cowboy_req:binding(setting_key, Req0),
30 5 case shurbej_db:get_setting(LibRef, SettingKey) of
31 {ok, #shurbej_setting{value = Value, version = Version}} ->
32 3 Body = #{<<"value">> => Value, <<"version">> => Version},
33 3 Req = shurbej_http_common:json_response(200, Body, Version, Req0),
34 3 {ok, Req, State};
35 undefined ->
36 2 Req = shurbej_http_common:error_response(404, <<"Setting not found">>, Req0),
37 2 {ok, Req, State}
38 end;
39
40 handle(<<"GET">>, Req0, State) ->
41 5 LibRef = shurbej_http_common:lib_ref(Req0),
42 5 Since = shurbej_http_common:get_since(Req0),
43 5 {ok, LibVersion} = shurbej_version:get(LibRef),
44 5 case shurbej_http_common:get_if_modified(Req0) of
45 V when is_integer(V), V >= LibVersion ->
46 1 Req = cowboy_req:reply(304, #{
47 <<"last-modified-version">> => integer_to_binary(LibVersion)
48 }, Req0),
49 1 {ok, Req, State};
50 4 _ -> handle_get_list(Req0, LibRef, Since, LibVersion, State)
51 end;
52
53 handle(<<"POST">>, Req0, State) ->
54 4 {LT, LI} = LibRef = shurbej_http_common:lib_ref(Req0),
55 4 ExpectedVersion = shurbej_http_common:get_if_unmodified(Req0),
56 4 case shurbej_http_common:read_json_body(Req0) of
57 {error, _, Req1} ->
58
:-(
Req = shurbej_http_common:error_response(400, <<"Invalid JSON">>, Req1),
59
:-(
{ok, Req, State};
60 {ok, SettingsMap, Req1} when is_map(SettingsMap) ->
61 %% Validate each setting
62 4 Errors = maps:fold(fun(Key, ValObj, Acc) ->
63 4 Value = case is_map(ValObj) of
64 4 true -> maps:get(<<"value">>, ValObj, ValObj);
65
:-(
false -> ValObj
66 end,
67 4 case shurbej_validate:setting(Key, Value) of
68 3 ok -> Acc;
69 1 {error, Reason} -> [{Key, Reason} | Acc]
70 end
71 end, [], SettingsMap),
72 4 case Errors of
73 [{BadKey, Reason} | _] ->
74 1 Req = shurbej_http_common:error_response(400,
75 <<"Invalid setting '", BadKey/binary, "': ", Reason/binary>>, Req1),
76 1 {ok, Req, State};
77 [] ->
78 3 case shurbej_version:write(LibRef, ExpectedVersion, fun(NewVersion) ->
79 2 maps:foreach(fun(Key, ValObj) ->
80 2 Value = case is_map(ValObj) of
81 2 true -> maps:get(<<"value">>, ValObj, ValObj);
82
:-(
false -> ValObj
83 end,
84 2 shurbej_db:write_setting(#shurbej_setting{
85 id = {LT, LI, Key},
86 version = NewVersion,
87 value = Value
88 })
89 end, SettingsMap),
90 2 ok
91 end) of
92 {ok, NewVersion} ->
93 2 Req = cowboy_req:reply(204, #{
94 <<"last-modified-version">> => integer_to_binary(NewVersion)
95 }, Req1),
96 2 {ok, Req, State};
97 {error, precondition, CurrentVersion} ->
98 1 Req = shurbej_http_common:json_response(412,
99 #{<<"message">> => <<"Library has been modified since specified version">>},
100 CurrentVersion, Req1),
101 1 {ok, Req, State}
102 end
103 end;
104 {ok, _, Req1} ->
105
:-(
Req = shurbej_http_common:error_response(400, <<"Body must be a JSON object">>, Req1),
106
:-(
{ok, Req, State}
107 end;
108
109 %% PUT /settings/:setting_key — create or update a single setting
110 handle(<<"PUT">>, Req0, #{scope := single} = State) ->
111 2 {LT, LI} = LibRef = shurbej_http_common:lib_ref(Req0),
112 2 SettingKey = cowboy_req:binding(setting_key, Req0),
113 2 ExpectedVersion = shurbej_http_common:get_if_unmodified(Req0),
114 2 case shurbej_http_common:read_json_body(Req0) of
115 {error, Reason, Req1} ->
116
:-(
Msg = case Reason of invalid_json -> <<"Invalid JSON">>; _ -> <<"Bad request">> end,
117
:-(
Req = shurbej_http_common:error_response(400, Msg, Req1),
118
:-(
{ok, Req, State};
119 {ok, Data, Req1} ->
120 2 Value = case is_map(Data) of
121 2 true -> maps:get(<<"value">>, Data, Data);
122
:-(
false -> Data
123 end,
124 2 case shurbej_validate:setting(SettingKey, Value) of
125 {error, Reason2} ->
126
:-(
Req = shurbej_http_common:error_response(400, Reason2, Req1),
127
:-(
{ok, Req, State};
128 ok ->
129 2 case shurbej_version:write(LibRef, ExpectedVersion, fun(NewVersion) ->
130 2 shurbej_db:write_setting(#shurbej_setting{
131 id = {LT, LI, SettingKey},
132 version = NewVersion,
133 value = Value
134 }),
135 2 ok
136 end) of
137 {ok, NewVersion} ->
138 2 Req = cowboy_req:reply(204, #{
139 <<"last-modified-version">> => integer_to_binary(NewVersion)
140 }, Req1),
141 2 {ok, Req, State};
142 {error, precondition, CurrentVersion} ->
143
:-(
Req = shurbej_http_common:json_response(412,
144 #{<<"message">> => <<"Library has been modified since specified version">>},
145 CurrentVersion, Req1),
146
:-(
{ok, Req, State}
147 end
148 end
149 end;
150
151 %% DELETE /settings/:setting_key
152 handle(<<"DELETE">>, Req0, #{scope := single} = State) ->
153 1 LibRef = shurbej_http_common:lib_ref(Req0),
154 1 SettingKey = cowboy_req:binding(setting_key, Req0),
155 1 ExpectedVersion = shurbej_http_common:get_if_unmodified(Req0),
156 1 case shurbej_version:write(LibRef, ExpectedVersion, fun(NewVersion) ->
157 1 shurbej_db:delete_setting(LibRef, SettingKey),
158 1 shurbej_db:record_deletion(LibRef, <<"setting">>, SettingKey, NewVersion),
159 1 ok
160 end) of
161 {ok, NewVersion} ->
162 1 Req = cowboy_req:reply(204, #{
163 <<"last-modified-version">> => integer_to_binary(NewVersion)
164 }, Req0),
165 1 {ok, Req, State};
166 {error, precondition, CurrentVersion} ->
167
:-(
Req = shurbej_http_common:json_response(412,
168 #{<<"message">> => <<"Library has been modified since specified version">>},
169 CurrentVersion, Req0),
170
:-(
{ok, Req, State}
171 end;
172
173 handle(_, Req0, State) ->
174
:-(
Req = shurbej_http_common:error_response(405, <<"Method not allowed">>, Req0),
175
:-(
{ok, Req, State}.
176
177 handle_get_list(Req0, LibRef, Since, LibVersion, State) ->
178 4 Format = shurbej_http_common:get_format(Req0),
179 4 case Format of
180 <<"versions">> ->
181 1 Pairs = shurbej_db:list_setting_versions(LibRef, Since),
182 1 Req = shurbej_http_common:json_response(200, maps:from_list(Pairs), LibVersion, Req0),
183 1 {ok, Req, State};
184 _ ->
185 3 Settings = shurbej_db:list_settings(LibRef, Since),
186 3 Map = maps:from_list([{Key, #{<<"value">> => S#shurbej_setting.value,
187 <<"version">> => S#shurbej_setting.version}}
188 3 || #shurbej_setting{id = {_, _, Key}} = S <- Settings]),
189 3 Req = shurbej_http_common:json_response(200, Map, LibVersion, Req0),
190 3 {ok, Req, State}
191 end.
Line Hits Source