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:
parent
cd923838c3
commit
bf98fa0c01
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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.
|
Loading…
Reference in New Issue
Block a user