Merge branch 'api-redesign' into client-redesign

This commit is contained in:
Jonathan Bernard
2011-05-03 12:40:06 -05:00
9 changed files with 54 additions and 53 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+44 -44
View File
@@ -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) ->
+2 -2
View File
@@ -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:
+8 -7
View File
@@ -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) ->