25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-26 17:38:45 +01:00

Added node creation with configure form

Added deletion
Better behavior in case of a crash (returns 500)
This commit is contained in:
Eric Cestari 2010-09-07 14:35:40 +02:00
parent cd923838c3
commit bf98fa0c01
3 changed files with 86 additions and 25 deletions

View File

@ -13,33 +13,67 @@ Also, in the ejabberd_http handler configuration, add the identified line.
{request_handlers, [{["pshb"], pshb_http}]} % this should be added {request_handlers, [{["pshb"], pshb_http}]} % this should be added
]} ]}
## Important notice ##
In the current version of the code, some security checks are not done :
* read operations can all be done without authentication
* node creation uses the default `all` access_createnode acl, not checking for the actual configuration.
## Usage example with cURL ## ## Usage example with cURL ##
### Getting the service document ### ### Getting the service document ###
No authentication necessary. All nodes are listed. No authentication necessary. All nodes are listed.
curl -i http://<host>:<port>/pshb/<domain>/ curl -i http://host:port/pshb/domain/
### Getting items from a node ### ### Getting items from a node ###
No authentication done, and all nodes are accessible. No authentication done, and all nodes are accessible.
curl -i http://<host>:<port>/pshb/<domain>/<node>/ curl -i http://host:port/pshb/domain/node/
### Posting a new item ### ### Posting a new item ###
curl -u <jid>:<password> -i -X POST -d @entry.atom http://<host>:<port>/pshb/<domain>/<node> curl -u jid:password -i -X POST -d @entry.atom http://post:port/pshb/domain/node
User ability to post is based on node configuration. User ability to post is based on node configuration.
### Creating a new node ### ### Creating a new node ###
An instant node can be created : An instant node can be created if server configuration allows:
curl -X POST -u cstar@localhost:encore -d "" http://localhost:5280/pshb/localhost curl -X POST -u cstar@localhost:encore -d "" http://localhost:5280/pshb/localhost
or
curl -X POST -u cstar@localhost:encore -d "<pubsub><create node='princely_musings'/></pubsub>" http://localhost:5280/pshb/localhost
configure element (as per XEP-60) can be passed in the pubsub body.
$ cat createnode.xml
<pubsub><create node='princely_musings' type='flat'/>
<x xmlns='jabber:x:data' type='submit'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/pubsub#node_config</value>
</field>
<field var='pubsub#title'><value>Princely Musings (Atom)</value></field>
<field var='pubsub#max_payload_size'><value>1028</value></field>
<field var='pubsub#type'><value>Atom</value></field>
</x>
</pubsub>
$ curl -X POST -u cstar@localhost:encore -d @createnode.xml http://localhost:5280/pshb/localhost
### Deleting a node ###
A node is deleted by:
curl -X DELETE -u cstar@localhost:encore http://localhost:5280/pshb/localhost/princely_musings

View File

@ -78,6 +78,7 @@
%% exports for console debug manual use %% exports for console debug manual use
-export([create_node/5, -export([create_node/5,
create_node/7,
delete_node/3, delete_node/3,
subscribe_node/5, subscribe_node/5,
unsubscribe_node/5, unsubscribe_node/5,

View File

@ -48,35 +48,36 @@
process(LocalPath, #request{auth = Auth} = Request)-> process(LocalPath, #request{auth = Auth} = Request)->
?DEBUG("LocalPath = ~p", [LocalPath]), ?DEBUG("LocalPath = ~p", [LocalPath]),
case get_auth(Auth) of UD = get_auth(Auth),
%%make sure user belongs to pubsub domain case catch out(Request, Request#request.method, LocalPath,UD) of
{User, Domain} -> {'EXIT', Error} ->
out(Request, Request#request.method, LocalPath,{User, Domain}); ?ERROR_MSG("Error while processing ~p : ~n~p", [LocalPath, Error]),
_ -> error(500);
out(Request, Request#request.method, LocalPath, undefined) Result ->
end. Result
end.
get_auth(Auth) -> get_auth(Auth) ->
case Auth of case Auth of
{SJID, P} -> {SJID, P} ->
case jlib:string_to_jid(SJID) of case jlib:string_to_jid(SJID) of
error -> error ->
unauthorized; undefined;
#jid{user = U, server = S} -> #jid{user = U, server = S} ->
case ejabberd_auth:check_password(U, S, P) of case ejabberd_auth:check_password(U, S, P) of
true -> true ->
{U, S}; {U, S};
false -> false ->
unauthorized undefined
end end
end; end;
_ -> _ ->
unauthorized undefined
end. end.
out(Args, 'GET', [Domain,Node]=Uri, _User) -> out(Args, 'GET', [Domain,Node]=Uri, _User) ->
case mod_pubsub:tree_action(get_host(Uri), get_node, [get_host(Uri),get_collection(Uri)]) of case mod_pubsub:tree_action(get_host(Uri), get_node, [get_host(Uri),get_collection(Uri)]) of
{error, _} -> error(404); {error, Error} -> error(Error);
_ -> _ ->
Items = lists:sort(fun(X,Y)-> Items = lists:sort(fun(X,Y)->
{DateX, _} = X#pubsub_item.modification, {DateX, _} = X#pubsub_item.modification,
@ -135,7 +136,7 @@ out(Args, 'GET', [Domain]=Uri, From)->
case mod_pubsub:tree_action(Host, get_subnodes, [Host, <<>>, From ]) of case mod_pubsub:tree_action(Host, get_subnodes, [Host, <<>>, From ]) of
[] -> [] ->
?DEBUG("Error getting URI ~p : ~p",[Uri, From]), ?DEBUG("Error getting URI ~p : ~p",[Uri, From]),
error(404); error(?ERR_ITEM_NOT_FOUND);
Collections -> Collections ->
{200, [{"Content-Type", "application/atomsvc+xml"}], "<?xml version=\"1.0\" encoding=\"utf-8\"?>" {200, [{"Content-Type", "application/atomsvc+xml"}], "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
++ xml:element_to_string(service(Args,Domain, Collections))} ++ xml:element_to_string(service(Args,Domain, Collections))}
@ -143,18 +144,37 @@ out(Args, 'GET', [Domain]=Uri, From)->
out(Args, 'POST', [Domain]=Uri, {User, UDomain})-> out(Args, 'POST', [Domain]=Uri, {User, UDomain})->
Host = get_host(Uri), Host = get_host(Uri),
case mod_pubsub:create_node(Host, Domain, <<>>, {User, UDomain}, "default") of Payload = xml_stream:parse_element(Args#request.data),
{Node, Type} = case xml:get_subtag(Payload, "create") of
false -> {<<>>,"flat"};
E ->
{list_to_binary(get_tag_attr_or_default("node", E,"")),
get_tag_attr_or_default("type", E,"flat")}
end,
ConfigureElement = case xml:get_subtag(Payload, "configure") of
false ->[];
{xmlelement, _, _, SubEls}->SubEls
end,
Jid = jlib:make_jid({User, UDomain, ""}),
case mod_pubsub:create_node(Host, Domain, Node, Jid, Type, all, ConfigureElement) of
{error, Error} -> {error, Error} ->
?ERROR_MSG("Error create node via HTTP : ~p",[Error]), ?ERROR_MSG("Error create node via HTTP : ~p",[Error]),
error(Error); % will probably detail more error(Error); % will probably detail more
{result, [Node]} -> {result, [Result]} ->
{200, [{"Content-Type", "application/xml"}], "<?xml version=\"1.0\" encoding=\"utf-8\"?>" {200, [{"Content-Type", "application/xml"}], "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
++ xml:element_to_string(Node)} ++ xml:element_to_string(Result)}
end; end;
out(Args, 'POST', [Domain]=Uri, undefined) -> out(Args, 'DELETE', [Domain, Node] = Uri, {User, UDomain})->
error(403); Host = get_host(Uri),
Jid = jlib:make_jid({User, UDomain, ""}),
BinNode = list_to_binary(Node),
case mod_pubsub:delete_node(Host, BinNode, Jid) of
{error, Error} -> error(Error);
{result, []} ->
{200, [],[]}
end;
@ -178,7 +198,7 @@ out(Args, 'GET', [Domain, Node, _Item]=URI, _) ->
out(_,Method,Uri,undefined) -> out(_,Method,Uri,undefined) ->
?DEBUG("Error, ~p not authorized for ~p : ~p",[ Method,Uri]), ?DEBUG("Error, ~p not authorized for ~p : ~p",[ Method,Uri]),
error(403). error(?ERR_FORBIDDEN).
get_item(Uri, Failure, Success)-> get_item(Uri, Failure, Success)->
?DEBUG(" mod_pubsub:get_item(~p, ~p,~p)", [get_host(Uri), get_collection(Uri), get_member(Uri)]), ?DEBUG(" mod_pubsub:get_item(~p, ~p,~p)", [get_host(Uri), get_collection(Uri), get_member(Uri)]),
@ -342,3 +362,9 @@ i2l(L) when is_list(L) -> L.
b2l(B) when is_binary(B) -> binary_to_list(B); b2l(B) when is_binary(B) -> binary_to_list(B);
b2l(L) when is_list(L) -> L. b2l(L) when is_list(L) -> L.
get_tag_attr_or_default(AttrName, Element, Default)->
case xml:get_tag_attr_s(AttrName, Element) of
"" -> Default;
Val -> Val
end.