Merge branch 'api-redesign' into client-redesign
This commit is contained in:
commit
cf5153c90b
BIN
db/test/id_counter.DCL
Normal file
BIN
db/test/id_counter.DCL
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
db/test/ts_timeline.DCL
Normal file
BIN
db/test/ts_timeline.DCL
Normal file
Binary file not shown.
Binary file not shown.
@ -34,19 +34,18 @@ out(YArg) ->
|
||||
dispatch_request(YArg, _Session, []) -> make_json_404(YArg, [{see_docs, "/ts_api_doc"}]);
|
||||
|
||||
dispatch_request(YArg, Session, [H|T]) ->
|
||||
Param = path_element_to_atom(H),
|
||||
|
||||
case {Session, Param} of
|
||||
{_, login} -> do_login(YArg);
|
||||
{_, logout} -> do_logout(YArg);
|
||||
case {Session, H} of
|
||||
{_, "login"} -> do_login(YArg);
|
||||
{_, "logout"} -> do_logout(YArg);
|
||||
|
||||
{not_logged_in, _} -> make_json_401(YArg);
|
||||
{session_expired, _} -> make_json_401(YArg, [{error, "session expired"}]);
|
||||
{"not_logged_in", _} -> make_json_401(YArg);
|
||||
{"session_expired", _} -> make_json_401(YArg, [{error, "session expired"}]);
|
||||
|
||||
{_S, app} -> dispatch_app(YArg, Session, T);
|
||||
{_S, users} -> dispatch_user(YArg, Session, T);
|
||||
{_S, timelines} -> dispatch_timeline(YArg, Session, T);
|
||||
{_S, entries} -> dispatch_entry(YArg, Session, T);
|
||||
{_S, "app"} -> dispatch_app(YArg, Session, T);
|
||||
{_S, "users"} -> dispatch_user(YArg, Session, T);
|
||||
{_S, "timelines"} -> dispatch_timeline(YArg, Session, T);
|
||||
{_S, "entries"} -> dispatch_entry(YArg, Session, T);
|
||||
{_S, _Other} -> make_json_404(YArg, [{see_docs, "/ts_api_doc/"}])
|
||||
end.
|
||||
|
||||
@ -59,7 +58,7 @@ dispatch_app(YArg, Session, Params) ->
|
||||
|
||||
{'GET', ["user_summary", UsernameStr]} ->
|
||||
case {Session#ts_api_session.username,
|
||||
path_element_to_atom(UsernameStr)} of
|
||||
UsernameStr} of
|
||||
|
||||
{Username, Username} -> get_user_summary(YArg, Username);
|
||||
_ -> make_json_401(YArg)
|
||||
@ -75,10 +74,9 @@ dispatch_app(YArg, Session, Params) ->
|
||||
% -------- Dispatch for /user -------- %
|
||||
|
||||
dispatch_user(YArg, Session, []) ->
|
||||
dispatch_user(YArg, Session, [atom_to_list(Session#ts_api_session.username)]);
|
||||
dispatch_user(YArg, Session, [Session#ts_api_session.username]);
|
||||
|
||||
dispatch_user(YArg, Session, [H]) ->
|
||||
Username = path_element_to_atom(H),
|
||||
dispatch_user(YArg, Session, [Username]) ->
|
||||
HTTPMethod = (YArg#arg.req)#http_request.method,
|
||||
|
||||
% compare to the logged-in user
|
||||
@ -97,8 +95,7 @@ dispatch_user(YArg, Session, [H]) ->
|
||||
dispatch_timeline(YArg, _Session, []) ->
|
||||
make_json_404(YArg, [{see_docs, "/ts_api_doc/timelines.html"}]);
|
||||
|
||||
dispatch_timeline(YArg, Session, [UrlUsername|_T] = PathElements) ->
|
||||
Username = path_element_to_atom(UrlUsername),
|
||||
dispatch_timeline(YArg, Session, [Username|_T] = PathElements) ->
|
||||
|
||||
case Session#ts_api_session.username of
|
||||
Username -> dispatch_timeline(YArg, PathElements);
|
||||
@ -106,8 +103,7 @@ dispatch_timeline(YArg, Session, [UrlUsername|_T] = PathElements) ->
|
||||
end.
|
||||
|
||||
% just username, list timelines
|
||||
dispatch_timeline(YArg, [UrlUsername]) ->
|
||||
Username = path_element_to_atom(UrlUsername),
|
||||
dispatch_timeline(YArg, [Username]) ->
|
||||
HTTPMethod = (YArg#arg.req)#http_request.method,
|
||||
|
||||
case HTTPMethod of
|
||||
@ -115,9 +111,7 @@ dispatch_timeline(YArg, [UrlUsername]) ->
|
||||
_Other -> make_json_405(YArg, [{see_docs, "/ts_api_doc/timelines.html"}])
|
||||
end;
|
||||
|
||||
dispatch_timeline(YArg, [UrlUsername, UrlTimelineId]) ->
|
||||
Username = path_element_to_atom(UrlUsername),
|
||||
TimelineId = path_element_to_atom(UrlTimelineId),
|
||||
dispatch_timeline(YArg, [Username, TimelineId]) ->
|
||||
HTTPMethod = (YArg#arg.req)#http_request.method,
|
||||
|
||||
case HTTPMethod of
|
||||
@ -136,17 +130,14 @@ dispatch_timeline(YArg, _Other) ->
|
||||
dispatch_entry(YArg, _Session, []) ->
|
||||
make_json_404(YArg, [{see_docs, "/ts_aip_doc/entries.html"}]);
|
||||
|
||||
dispatch_entry(YArg, Session, [UrlUsername|_T] = PathElements) ->
|
||||
Username = path_element_to_atom(UrlUsername),
|
||||
dispatch_entry(YArg, Session, [Username|_T] = PathElements) ->
|
||||
|
||||
case Session#ts_api_session.username of
|
||||
Username -> dispatch_entry(YArg, PathElements);
|
||||
_Other -> make_json_404(YArg, [{see_docs, "/ts_api_doc/entries.html"}])
|
||||
end.
|
||||
|
||||
dispatch_entry(YArg, [UrlUsername, UrlTimelineId]) ->
|
||||
Username = path_element_to_atom(UrlUsername),
|
||||
TimelineId = path_element_to_atom(UrlTimelineId),
|
||||
dispatch_entry(YArg, [Username, TimelineId]) ->
|
||||
HTTPMethod = (YArg#arg.req)#http_request.method,
|
||||
|
||||
case HTTPMethod of
|
||||
@ -155,9 +146,7 @@ dispatch_entry(YArg, [UrlUsername, UrlTimelineId]) ->
|
||||
_Other -> make_json_405(YArg, [{see_docs, "/ts_api_doc/entries.html"}])
|
||||
end;
|
||||
|
||||
dispatch_entry(YArg, [UrlUsername, UrlTimelineId, UrlEntryId]) ->
|
||||
Username = path_element_to_atom(UrlUsername),
|
||||
TimelineId = path_element_to_atom(UrlTimelineId),
|
||||
dispatch_entry(YArg, [Username, TimelineId, UrlEntryId]) ->
|
||||
EntryId = list_to_integer(UrlEntryId), % TODO: catch non-numbers
|
||||
HTTPMethod = (YArg#arg.req)#http_request.method,
|
||||
|
||||
@ -184,8 +173,7 @@ do_login(YArg) ->
|
||||
lists:keyfind(password, 1, Fields)} of
|
||||
|
||||
% username and password found
|
||||
{{username, UnameField}, {password, Password}} ->
|
||||
Username = list_to_atom(UnameField),
|
||||
{{username, Username}, {password, Password}} ->
|
||||
|
||||
% check the uname, password
|
||||
case ts_user:check_credentials(Username, Password) of
|
||||
@ -281,7 +269,11 @@ post_timeline(YArg, Username, TimelineId) ->
|
||||
EJSON = parse_json_body(YArg),
|
||||
|
||||
% parse into a Timeline record
|
||||
TR = ts_json:ejson_to_record(#ts_timeline{}, EJSON),
|
||||
TR = try ts_json:ejson_to_record(#ts_timeline{}, EJSON)
|
||||
catch _:InputError ->
|
||||
error_logger:error_report("Bad input: ~p", [InputError]),
|
||||
throw(make_json_400(YArg))
|
||||
end,
|
||||
|
||||
% set username and timeline id
|
||||
NewRecord = TR#ts_timeline{ref = {Username, TimelineId}},
|
||||
@ -309,12 +301,16 @@ put_timeline(YArg, Username, TimelineId) ->
|
||||
%{struct, Fields} = EJSON,
|
||||
|
||||
% parse into a timeline record
|
||||
TR = ts_json:ejson_to_record(#ts_timeline{}, EJSON),
|
||||
TR = try ts_json:ejson_to_record(#ts_timeline{}, EJSON)
|
||||
catch _:InputError ->
|
||||
error_logger:error_report("Bad input: ~p", [InputError]),
|
||||
throw(make_json_400(YArg))
|
||||
end,
|
||||
|
||||
% not supported right now, would require changing all the entry keys
|
||||
% check to see if they are changing the timeline id
|
||||
%NewTimelineId = case lists:keyfind(1, timeline_id, Fields) of
|
||||
% {timeline_id, Field} -> list_to_atom(Field);
|
||||
% {timeline_id, Field} -> Field;
|
||||
% false -> TimelineId end,
|
||||
|
||||
% set username and timeline id
|
||||
@ -428,7 +424,11 @@ post_entry(YArg, Username, TimelineId) ->
|
||||
EJSON = parse_json_body(YArg),
|
||||
|
||||
% parse into ts_entry record
|
||||
ER = ts_json:ejson_to_record(#ts_entry{}, EJSON),
|
||||
ER = try ts_json:ejson_to_record(#ts_entry{}, EJSON)
|
||||
catch _:InputError ->
|
||||
error_logger:error_report("Bad input: ~p", [InputError]),
|
||||
throw(make_json_400(YArg))
|
||||
end,
|
||||
|
||||
% set username and timeline id
|
||||
NewRecord = ER#ts_entry{ref = {Username, TimelineId, undef}},
|
||||
@ -455,7 +455,11 @@ put_entry(YArg, Username, TimelineId, EntryId) ->
|
||||
EJSON = parse_json_body(YArg),
|
||||
|
||||
% parse into ts_entry record
|
||||
ER = ts_json:ejson_to_record(#ts_entry{}, EJSON),
|
||||
ER = try ts_json:ejson_to_record(#ts_entry{}, EJSON)
|
||||
catch _:InputError ->
|
||||
error_logger:error_report("Bad input: ~p", [InputError]),
|
||||
throw(make_json_400(YArg))
|
||||
end,
|
||||
|
||||
% set uername, timeline id, and entry id
|
||||
NewRecord = ER#ts_entry{ref = {Username, TimelineId, EntryId}},
|
||||
@ -492,10 +496,6 @@ delete_entry(YArg, Username, TimelineId, EntryId) ->
|
||||
% ======== UTIL METHODS ======== %
|
||||
% ============================== %
|
||||
|
||||
%% Convert one path element to an atom.
|
||||
path_element_to_atom(PE) ->
|
||||
list_to_atom(re:replace(PE, "\\s", "_", [{return, list}])).
|
||||
|
||||
parse_json_body(YArg) ->
|
||||
case catch json:decode([], binary_to_list(YArg#arg.clidata)) of
|
||||
{done, {ok, EJSON}, _} -> EJSON;
|
||||
@ -547,19 +547,19 @@ make_json_405(YArg) -> make_json_405(YArg, []).
|
||||
make_json_405(YArg, Fields) ->
|
||||
% add default status if not provided
|
||||
F1 = case lists:keyfind(status, 1, Fields) of
|
||||
false -> Fields ++ [{status, method_not_allowed}];
|
||||
false -> Fields ++ [{status, "method not allowed"}];
|
||||
_Else -> Fields
|
||||
end,
|
||||
|
||||
% add the path they requested
|
||||
F2 = F1 ++ [{path, (YArg#arg.req)#http_request.path}],
|
||||
% F2 = F1 ++ [{path, io_lib:format("~s", [(YArg#arg.req)#http_request.path])}],
|
||||
|
||||
[{status, 405}, {content, "application/json", json:encode({struct, F2})}].
|
||||
[{status, 405}, {content, "application/json", json:encode({struct, F1})}].
|
||||
|
||||
make_json_500(_YArg, Error) ->
|
||||
EJSON = {struct, [
|
||||
{status, "internal server error"},
|
||||
{error, io_lib:format("~p", [Error])}]},
|
||||
{error, io_lib:format("~s", [Error])}]},
|
||||
[{status, 500}, {content, "application/json", json:encode(EJSON)}].
|
||||
|
||||
make_json_500(_YArg) ->
|
||||
|
@ -4,8 +4,8 @@
|
||||
pwd_salt,
|
||||
name,
|
||||
email,
|
||||
join_date%,
|
||||
% ext_data % other extensible data
|
||||
join_date,
|
||||
ext_data = [] % other extensible data
|
||||
}).
|
||||
|
||||
% ts_user.ext_data can be:
|
||||
|
@ -7,10 +7,11 @@ encode_record(Record) -> lists:flatten(json:encode(record_to_ejson(Record))).
|
||||
|
||||
record_to_ejson(Record=#ts_user{}) ->
|
||||
{struct, [
|
||||
{id, atom_to_list(Record#ts_user.username)},
|
||||
{id, Record#ts_user.username},
|
||||
{name, Record#ts_user.name},
|
||||
{email, Record#ts_user.email},
|
||||
{join_date, encode_datetime(Record#ts_user.join_date)}]};
|
||||
{join_date, encode_datetime(Record#ts_user.join_date)},
|
||||
{ext_data, Record#ts_user.ext_data}]};
|
||||
|
||||
record_to_ejson(Record=#ts_timeline{}) ->
|
||||
% pull out the username and timeline id
|
||||
@ -18,8 +19,8 @@ record_to_ejson(Record=#ts_timeline{}) ->
|
||||
|
||||
% create the EJSON struct
|
||||
{struct, [
|
||||
{user_id, atom_to_list(Username)},
|
||||
{id, atom_to_list(TimelineId)},
|
||||
{user_id, Username},
|
||||
{id, TimelineId},
|
||||
{created, encode_datetime(Record#ts_timeline.created)},
|
||||
{description, Record#ts_timeline.desc}]};
|
||||
|
||||
@ -32,15 +33,15 @@ record_to_ejson(Record=#ts_entry{}) ->
|
||||
|
||||
% create the EJSON struct
|
||||
{struct, [
|
||||
{user_id, atom_to_list(Username)},
|
||||
{timeline_id, atom_to_list(TimelineId)},
|
||||
{user_id, Username},
|
||||
{timeline_id, TimelineId},
|
||||
{id, EntryId},
|
||||
{timestamp, encode_datetime(DateTime)},
|
||||
{mark, Record#ts_entry.mark},
|
||||
{notes, Record#ts_entry.notes}]}.
|
||||
|
||||
encode_datetime({{Year, Month, Day}, {Hour, Minute, Second}}) ->
|
||||
lists:flatten(io_lib:format("~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~2.10.0B~3.10.0BZ",
|
||||
lists:flatten(io_lib:format("~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~2.10.0B.~3.10.0BZ",
|
||||
[Year, Month, Day, Hour, Minute, Second, 000])).
|
||||
|
||||
ejson_to_record(_Empty=#ts_timeline{}, EJSON) ->
|
||||
|
Loading…
x
Reference in New Issue
Block a user