diff --git a/ChangeLog b/ChangeLog index 3ba623f37..b23db51fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-01-11 Christophe Romain + + * src/mod_pubsub/mod_pubsub.erl: fix owners cache and fix unsubscribe + permissions (thanks to Andy Skelton)(EJAB-840) + * src/mod_pubsub/node_default.erl: Likewise + 2009-01-10 Christophe Romain * src/mod_pubsub/node_default.erl: fix unsubscription of full jid diff --git a/src/mod_pubsub/mod_pubsub.erl b/src/mod_pubsub/mod_pubsub.erl index d7b05d32f..682a1aed8 100644 --- a/src/mod_pubsub/mod_pubsub.erl +++ b/src/mod_pubsub/mod_pubsub.erl @@ -1875,19 +1875,34 @@ set_affiliations(Host, Node, From, EntitiesEls) -> error -> {error, ?ERR_BAD_REQUEST}; _ -> - Action = fun(#pubsub_node{type = Type, owners = Owners}) -> - case lists:member(Owner, Owners) of - true -> - lists:foreach( - fun({JID, Affiliation}) -> - node_call( - Type, set_affiliation, - [Host, Node, JID, Affiliation]) - end, Entities), - {result, []}; - _ -> - {error, ?ERR_FORBIDDEN} - end + Action = fun(#pubsub_node{type = Type, owners = Owners}=N) -> + case lists:member(Owner, Owners) of + true -> + lists:foreach( + fun({JID, Affiliation}) -> + node_call(Type, set_affiliation, [Host, Node, JID, Affiliation]), + case Affiliation of + owner -> + NewOwner = jlib:jid_tolower(jlib:jid_remove_resource(JID)), + NewOwners = [NewOwner|Owners], + tree_call(Host, set_node, [N#pubsub_node{owners = NewOwners}]); + none -> + OldOwner = jlib:jid_tolower(jlib:jid_remove_resource(JID)), + case lists:member(OldOwner, Owners) of + true -> + NewOwners = Owners--[OldOwner], + tree_call(Host, set_node, [N#pubsub_node{owners = NewOwners}]); + _ -> + ok + end; + _ -> + ok + end + end, Entities), + {result, []}; + _ -> + {error, ?ERR_FORBIDDEN} + end end, transaction(Host, Node, Action, sync_dirty) end. diff --git a/src/mod_pubsub/node_default.erl b/src/mod_pubsub/node_default.erl index c1434087d..87b97dec3 100644 --- a/src/mod_pubsub/node_default.erl +++ b/src/mod_pubsub/node_default.erl @@ -275,22 +275,27 @@ subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> SubKey = jlib:jid_tolower(Subscriber), GenKey = jlib:jid_remove_resource(SubKey), - Authorized = (jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey), + SenderKey = jlib:jid_tolower(jlib:jid_remove_resource(Sender)), GenState = get_state(Host, Node, GenKey), SubState = case SubKey of GenKey -> GenState; _ -> get_state(Host, Node, SubKey) end, - Affiliation = GenState#pubsub_state.affiliation, - Subscription = SubState#pubsub_state.subscription, + Authorized = case SenderKey of + GenKey -> + true; + _ -> + SenderState = get_state(Host, Node, SenderKey), + SenderState#pubsub_state.affiliation == owner + end, if not Authorized -> %% JIDs do not match {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "invalid-jid")}; - Affiliation == outcast -> + GenState#pubsub_state.affiliation == outcast -> %% Requesting entity is blocked {error, ?ERR_FORBIDDEN}; - Subscription == pending -> + SubState#pubsub_state.subscription == pending -> %% Requesting entity has pending subscription {error, ?ERR_EXTENDED(?ERR_NOT_AUTHORIZED, "pending-subscription")}; (AccessModel == presence) and (not PresenceSubscription) -> @@ -345,14 +350,19 @@ subscribe_node(Host, Node, Sender, Subscriber, AccessModel, unsubscribe_node(Host, Node, Sender, Subscriber, _SubId) -> SubKey = jlib:jid_tolower(Subscriber), GenKey = jlib:jid_remove_resource(SubKey), - Authorized = (jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey), + SenderKey = jlib:jid_tolower(jlib:jid_remove_resource(Sender)), GenState = get_state(Host, Node, GenKey), SubState = case SubKey of GenKey -> GenState; _ -> get_state(Host, Node, SubKey) end, - Affiliation = GenState#pubsub_state.affiliation, - Subscription = SubState#pubsub_state.subscription, + Authorized = case SenderKey of + GenKey -> + true; + _ -> + SenderState = get_state(Host, Node, SenderKey), + SenderState#pubsub_state.affiliation == owner + end, if %% Entity did not specify SubID %%SubID == "", ?? -> @@ -361,10 +371,10 @@ unsubscribe_node(Host, Node, Sender, Subscriber, _SubId) -> %%InvalidSubID -> %% {error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; %% Requesting entity is not a subscriber - Subscription == none -> + SubState#pubsub_state.subscription == none -> {error, ?ERR_EXTENDED(?ERR_UNEXPECTED_REQUEST, "not-subscribed")}; %% Requesting entity is prohibited from unsubscribing entity - (not Authorized) and (Affiliation =/= owner) -> + not Authorized -> {error, ?ERR_FORBIDDEN}; %% Was just subscriber, remove the record SubState#pubsub_state.affiliation == none -> @@ -576,7 +586,12 @@ set_affiliation(Host, Node, Owner, Affiliation) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), GenState = get_state(Host, Node, GenKey), - set_state(GenState#pubsub_state{affiliation = Affiliation}), + case {Affiliation, GenState#pubsub_state.subscription} of + {none, none} -> + del_state(GenState#pubsub_state.stateid); + _ -> + set_state(GenState#pubsub_state{affiliation = Affiliation}) + end, ok. %% @spec (Host, Ownner) -> [{Node,Subscription}] @@ -619,7 +634,12 @@ get_subscription(Host, Node, Owner) -> set_subscription(Host, Node, Owner, Subscription) -> SubKey = jlib:jid_tolower(Owner), SubState = get_state(Host, Node, SubKey), - set_state(SubState#pubsub_state{subscription = Subscription}), + case {Subscription, SubState#pubsub_state.affiliation} of + {none, none} -> + del_state(SubState#pubsub_state.stateid); + _ -> + set_state(SubState#pubsub_state{subscription = Subscription}) + end, ok. %% @spec (Host, Node) -> [States] | [] @@ -690,7 +710,6 @@ get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, _SubI SubKey = jlib:jid_tolower(JID), GenKey = jlib:jid_remove_resource(SubKey), GenState = get_state(Host, Node, GenKey), - Affiliation = GenState#pubsub_state.affiliation, if %%SubID == "", ?? -> %% Entity has multiple subscriptions to the node but does not specify a subscription ID @@ -698,7 +717,7 @@ get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, _SubI %%InvalidSubID -> %% Entity is subscribed but specifies an invalid subscription ID %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - Affiliation == outcast -> + GenState#pubsub_state.affiliation == outcast -> %% Requesting entity is blocked {error, ?ERR_FORBIDDEN}; (AccessModel == presence) and (not PresenceSubscription) -> @@ -737,7 +756,6 @@ get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup SubKey = jlib:jid_tolower(JID), GenKey = jlib:jid_remove_resource(SubKey), GenState = get_state(Host, Node, GenKey), - Affiliation = GenState#pubsub_state.affiliation, if %%SubID == "", ?? -> %% Entity has multiple subscriptions to the node but does not specify a subscription ID @@ -745,7 +763,7 @@ get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup %%InvalidSubID -> %% Entity is subscribed but specifies an invalid subscription ID %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - Affiliation == outcast -> + GenState#pubsub_state.affiliation == outcast -> %% Requesting entity is blocked {error, ?ERR_FORBIDDEN}; (AccessModel == presence) and (not PresenceSubscription) ->