1: %%==============================================================================
    2: %% Copyright 2010 Erlang Solutions Ltd.
    3: %%
    4: %% Licensed under the Apache License, Version 2.0 (the "License");
    5: %% you may not use this file except in compliance with the License.
    6: %% You may obtain a copy of the License at
    7: %%
    8: %% http://www.apache.org/licenses/LICENSE-2.0
    9: %%
   10: %% Unless required by applicable law or agreed to in writing, software
   11: %% distributed under the License is distributed on an "AS IS" BASIS,
   12: %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13: %% See the License for the specific language governing permissions and
   14: %% limitations under the License.
   15: %%==============================================================================
   16: 
   17: -module(privacy_SUITE).
   18: -compile([export_all, nowarn_export_all]).
   19: 
   20: -include_lib("exml/include/exml.hrl").
   21: -include_lib("escalus/include/escalus.hrl").
   22: -include_lib("common_test/include/ct.hrl").
   23: -include_lib("escalus/include/escalus_xmlns.hrl").
   24: 
   25: -define(SLEEP_TIME, 50).
   26: 
   27: %%--------------------------------------------------------------------
   28: %% Suite configuration
   29: %%--------------------------------------------------------------------
   30: 
   31: all() ->
   32:     [
   33:      {group, management},
   34:      {group, blocking},
   35:      {group, allowing}
   36:     ].
   37: 
   38: groups() ->
   39:     G = [{management, [parallel], management_test_cases()},
   40:          {blocking, [parallel], blocking_test_cases()},
   41:          {allowing, [parallel], allowing_test_cases()}],
   42:     ct_helper:repeat_all_until_all_ok(G).
   43: 
   44: management_test_cases() ->
   45:     [
   46:      discover_support,
   47:      get_all_lists,
   48:      get_existing_list,
   49:      get_many_lists,
   50:      get_nonexistent_list,
   51:      set_list,
   52:      activate,
   53:      activate_nonexistent,
   54:      deactivate,
   55:      default,
   56:      %default_conflict,  % fails, as of bug #7073
   57:      default_nonexistent,
   58:      no_default,
   59:      remove_list,
   60:      get_all_lists_with_active,
   61:      get_all_lists_with_default
   62:     ].
   63: 
   64: blocking_test_cases() ->
   65:     [
   66:      block_jid_message,
   67:      block_group_message,
   68:      block_subscription_message,
   69:      block_all_message,
   70:      block_jid_presence_in,
   71:      block_jid_presence_out,
   72:      block_jid_iq,
   73:      block_jid_all,
   74:      block_jid_message_but_not_presence,
   75:      newly_blocked_presense_jid_by_new_list,
   76:      newly_blocked_presense_jid_by_list_change,
   77:      newly_blocked_presence_not_notify_self,
   78:      iq_reply_doesnt_crash_user_process
   79:     ].
   80: 
   81: allowing_test_cases() ->
   82:     [allow_subscription_to_from_message,
   83:      allow_subscription_both_message].
   84: 
   85: suite() ->
   86:     escalus:suite().
   87: 
   88: %%--------------------------------------------------------------------
   89: %% Init & teardown
   90: %%--------------------------------------------------------------------
   91: 
   92: init_per_suite(Config0) ->
   93:     HostType = domain_helper:host_type(),
   94:     Config1 = dynamic_modules:save_modules(HostType, Config0),
   95:     Backend = mongoose_helper:get_backend_mnesia_rdbms_riak(HostType),
   96:     ModConfig = [{mod_privacy, set_opts(Backend)}],
   97:     dynamic_modules:ensure_modules(HostType, ModConfig),
   98:     [{escalus_no_stanzas_after_story, true},
   99:      {backend, Backend} |
  100:      escalus:init_per_suite(Config1)].
  101: 
  102: set_opts(riak) ->
  103:     #{riak => config_parser_helper:config([modules, mod_privacy, riak], #{}), backend => riak};
  104: set_opts(Backend) ->
  105:     #{backend => Backend}.
  106: 
  107: end_per_suite(Config) ->
  108:     escalus_fresh:clean(),
  109:     dynamic_modules:restore_modules(Config),
  110:     escalus:end_per_suite(Config).
  111: 
  112: init_per_group(_GroupName, Config) ->
  113:     Config.
  114: 
  115: end_per_group(_GroupName, Config) ->
  116:     Config.
  117: 
  118: init_per_testcase(CaseName, Config) ->
  119:     escalus:init_per_testcase(CaseName, Config).
  120: 
  121: end_per_testcase(CaseName, Config) ->
  122:     escalus:end_per_testcase(CaseName, Config).
  123: 
  124: %%--------------------------------------------------------------------
  125: %% Tests
  126: %%--------------------------------------------------------------------
  127: 
  128: %% In terms of server response to blocked communication, we strive to implement the following
  129: %% as defined in XEP-0016:
  130: %% If someone I block tries to communicate with me, then the following rules apply:
  131: %%  * For presence stanzas (including notifications, subscriptions, and probes), the server MUST NOT respond and MUST NOT
  132: %%    return an error.
  133: %%  * For message stanzas, the server SHOULD return an error, which SHOULD be <service-unavailable/>.
  134: %%  * For IQ stanzas of type "get" or "set", the server MUST return an error, which SHOULD be <service-unavailable/>. IQ
  135: %%    stanzas of other types MUST be silently dropped by the server.
  136: %% If I want to communicate with someone I block, then:
  137: %%  * If the user attempts to send an outbound stanza to a contact and that stanza type is blocked, the user's server MUST
  138: %%    NOT route the stanza to the contact but instead MUST return a <not-acceptable/> error:
  139: 
  140: 
  141: %% TODO:
  142: %% x get all privacy lists
  143: %% x get single privacy list
  144: %%   x that exists
  145: %%   x that doesn't exist (ensure server returns item-not-found)
  146: %%   x request more than one at a time (ensure server returns bad-request)
  147: %% x set new/edit privacy list (ensure server pushes notifications
  148: %%   to all resources)
  149: %% - remove existing list
  150: %%   x remove existing list (ensure server push)
  151: %%   - remove, but check conflict case
  152: %% x manage active list(s)
  153: %%   x activate
  154: %%   x activate nonexistent (ensure item-not-found)
  155: %%   x deactivate by sending empty <active />
  156: %% - manage default list
  157: %%   x set default
  158: %%   - set default, but check the conflict case, i.e.:
  159: %%     "Client attempts to change the default list but that list is in use
  160: %%     by another resource",
  161: %%     !!! ejabberd doesn't support this, bug filed (#7073)
  162: %%   x set nonexistent default list
  163: %%   x use domain's routing, i.e. no default list -> send empty <default />
  164: %%   - set no default list, but check conflict case,
  165: %%     when a resource currently uses the default list
  166: %%
  167: %% TODO later:
  168: %% - big picture:
  169: %%   - blocking can be done on jids, roster groups,
  170: %%     subscription type or globally
  171: %%   - a blocking rule may block one or more of {message, presence-in,
  172: %%     presence-out, iqs} by specifying these as children to the list item
  173: %%     or block all of them, when the item has no children
  174: %% - blocking: messages, presence (in/out), iqs, all
  175: 
  176: discover_support(Config) ->
  177:     escalus:fresh_story(Config, [{alice, 1}], fun(Alice) ->
  178:         Server = escalus_client:server(Alice),
  179:         IqGet = escalus_stanza:disco_info(Server),
  180:         Result = escalus:send_iq_and_wait_for_result(Alice, IqGet),
  181:         escalus:assert(has_feature, [?NS_PRIVACY], Result)
  182:     end).
  183: 
  184: get_all_lists(Config) ->
  185:     escalus:fresh_story(Config, [{alice, 1}], fun(Alice) ->
  186: 
  187:         escalus:send(Alice, escalus_stanza:privacy_get_all()),
  188:         escalus:assert(is_privacy_result, escalus:wait_for_stanza(Alice))
  189: 
  190:         end).
  191: 
  192: get_all_lists_with_active(Config) ->
  193:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  194: 
  195:         privacy_helper:set_and_activate(Alice, {<<"deny_client">>, Bob}),
  196: 
  197:         escalus:send(Alice, escalus_stanza:privacy_get_all()),
  198:         escalus:assert(is_privacy_result_with_active, [<<"deny_client">>],
  199:                        escalus:wait_for_stanza(Alice))
  200: 
  201:         end).
  202: 
  203: get_all_lists_with_default(Config) ->
  204:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  205: 
  206:         privacy_helper:set_list(Alice, {<<"deny_client">>, Bob}),
  207:         privacy_helper:set_list(Alice, {<<"allow_client">>, Bob}),
  208:         privacy_helper:set_default_list(Alice, <<"allow_client">>),
  209: 
  210:         escalus:send(Alice, escalus_stanza:privacy_get_all()),
  211:         escalus:assert(is_privacy_result_with_default,
  212:                        escalus:wait_for_stanza(Alice))
  213: 
  214:         end).
  215: 
  216: get_nonexistent_list(Config) ->
  217:     escalus:fresh_story(Config, [{alice, 1}], fun(Alice) ->
  218: 
  219:         escalus_client:send(Alice,
  220:             escalus_stanza:privacy_get_lists([<<"public">>])),
  221:         escalus_assert:is_privacy_list_nonexistent_error(
  222:             escalus_client:wait_for_stanza(Alice))
  223: 
  224:         end).
  225: 
  226: get_many_lists(Config) ->
  227:     escalus:fresh_story(Config, [{alice, 1}], fun(Alice) ->
  228: 
  229:         Request = escalus_stanza:privacy_get_lists([<<"public">>, <<"private">>]),
  230:         escalus_client:send(Alice, Request),
  231:         Response = escalus_client:wait_for_stanza(Alice),
  232:         escalus_assert:is_error(Response, <<"modify">>, <<"bad-request">>)
  233: 
  234:         end).
  235: 
  236: get_existing_list(Config) ->
  237:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  238: 
  239:         privacy_helper:set_list(Alice, {<<"deny_client">>, Bob}),
  240: 
  241:         escalus:send(Alice, escalus_stanza:privacy_get_lists([<<"deny_client">>])),
  242:         Response = escalus:wait_for_stanza(Alice),
  243: 
  244:         <<"deny_client">> = exml_query:path(Response, [{element, <<"query">>},
  245:                                                        {element, <<"list">>},
  246:                                                        {attr, <<"name">>}])
  247: 
  248:         end).
  249: 
  250: activate(Config) ->
  251:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  252: 
  253:         privacy_helper:set_list(Alice, {<<"deny_client">>, Bob}),
  254: 
  255:         Request = escalus_stanza:privacy_activate(<<"deny_client">>),
  256:         escalus_client:send(Alice, Request),
  257: 
  258:         Response = escalus_client:wait_for_stanza(Alice),
  259:         escalus:assert(is_iq_result, Response)
  260: 
  261:         end).
  262: 
  263: activate_nonexistent(Config) ->
  264:     escalus:fresh_story(Config, [{alice, 1}], fun(Alice) ->
  265: 
  266:         Request = escalus_stanza:privacy_activate(<<"some_list">>),
  267:         escalus_client:send(Alice, Request),
  268: 
  269:         Response = escalus_client:wait_for_stanza(Alice),
  270:         escalus:assert(is_error, [<<"cancel">>, <<"item-not-found">>], Response)
  271: 
  272:         end).
  273: 
  274: deactivate(Config) ->
  275:     escalus:fresh_story(Config, [{alice, 1}], fun(Alice) ->
  276: 
  277:         Request = escalus_stanza:privacy_deactivate(),
  278:         escalus_client:send(Alice, Request),
  279: 
  280:         Response = escalus_client:wait_for_stanza(Alice),
  281:         escalus:assert(is_iq_result, Response)
  282: 
  283:         end).
  284: 
  285: default(Config) ->
  286:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  287: 
  288:         privacy_helper:set_list(Alice, {<<"deny_client">>, Bob}),
  289: 
  290:         Request = escalus_stanza:privacy_set_default(<<"deny_client">>),
  291:         escalus_client:send(Alice, Request),
  292: 
  293:         Response = escalus_client:wait_for_stanza(Alice),
  294:         escalus:assert(is_iq_result, Response)
  295: 
  296:         end).
  297: 
  298: default_conflict(Config) ->
  299:     escalus:fresh_story(Config, [{alice, 2}, {bob, 1}], fun(Alice, Alice2, Bob) ->
  300: 
  301:         %% testcase setup
  302:         %% setup list on server
  303:         privacy_helper:send_set_list(Alice, {<<"deny_client">>, Bob}),
  304:         privacy_helper:send_set_list(Alice, {<<"allow_client">>, Bob}),
  305:         %% skip responses
  306:         escalus_client:wait_for_stanzas(Alice, 4),
  307:         %% make a default list for Alice2
  308:         R1 = escalus_stanza:privacy_set_default(Alice2, <<"deny_client">>),
  309:         escalus_client:send(Alice2, R1),
  310:         escalus:assert_many([is_privacy_set, is_privacy_set, is_iq_result],
  311:                             escalus_client:wait_for_stanzas(Alice2, 3)),
  312:         %% setup done
  313: 
  314:         Request = escalus_stanza:privacy_set_default(<<"allow_client">>),
  315:         escalus_client:send(Alice, Request),
  316: 
  317:         Response = escalus_client:wait_for_stanza(Alice),
  318:         %% TODO: should fail on this (result) and receive error
  319:         %%       this is a bug and was filed to the esl redmine as Bug #7073
  320:         %true = exmpp_iq:is_result(Response),
  321:         %% but this should pass just fine
  322:         escalus:assert(is_error, [<<"cancel">>, <<"conflict">>], Response)
  323: 
  324:         end).
  325: 
  326: default_nonexistent(Config) ->
  327:     escalus:fresh_story(Config, [{alice, 1}], fun(Alice) ->
  328: 
  329:         Request = escalus_stanza:privacy_set_default(<<"some_list">>),
  330:         escalus_client:send(Alice, Request),
  331: 
  332:         Response = escalus_client:wait_for_stanza(Alice),
  333:         escalus_assert:is_error(Response, <<"cancel">>, <<"item-not-found">>)
  334: 
  335:         end).
  336: 
  337: no_default(Config) ->
  338:     escalus:fresh_story(Config, [{alice, 1}], fun(Alice) ->
  339: 
  340:         Request = escalus_stanza:privacy_no_default(),
  341:         escalus_client:send(Alice, Request),
  342: 
  343:         Response = escalus_client:wait_for_stanza(Alice),
  344:         escalus:assert(is_iq_result, Response)
  345: 
  346:         end).
  347: 
  348: set_list(Config) ->
  349:     escalus:fresh_story(Config, [{alice, 3}, {bob, 1}], fun(Alice, Alice2, Alice3, Bob) ->
  350: 
  351:         privacy_helper:send_set_list(Alice, {<<"deny_client">>, Bob}),
  352: 
  353:         %% Verify that original Alice gets iq result and notification.
  354:         %% It's a bit quirky as these come in undefined order
  355:         %% (actually, they always came with 'push' first and then 'result',
  356:         %% but I suppose it's not mandatory).
  357:         AliceResponses = escalus_client:wait_for_stanzas(Alice, 2),
  358:         escalus:assert_many([
  359:             fun escalus_pred:is_iq_result/1,
  360:             fun privacy_helper:is_privacy_list_push/1
  361:         ], AliceResponses),
  362: 
  363:         %% Verify that other resources also get the push.
  364:         escalus:assert(fun privacy_helper:is_privacy_list_push/1,
  365:                        escalus:wait_for_stanza(Alice2)),
  366:         escalus:assert(fun privacy_helper:is_privacy_list_push/1,
  367:                        escalus:wait_for_stanza(Alice3))
  368: 
  369:         %% All in all, the spec requires the resources to reply
  370:         %% (as to every iq), but it's omitted here.
  371: 
  372:         end).
  373: 
  374: remove_list(Config) ->
  375:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  376: 
  377:         privacy_helper:send_set_list(Alice, {<<"deny_client">>, Bob}),
  378: 
  379:         %% These are the pushed notification and iq result.
  380:         escalus_client:wait_for_stanzas(Alice, 2),
  381: 
  382:         %% Request list deletion by sending an empty list.
  383:         RemoveRequest = escalus_stanza:privacy_set_list(
  384:                           escalus_stanza:privacy_list(<<"someList">>, [])),
  385:         escalus_client:send(Alice, RemoveRequest),
  386: 
  387:         %% These too are the pushed notification and iq result.
  388:         escalus:assert_many([
  389:             fun privacy_helper:is_privacy_list_push/1,
  390:             is_iq_result
  391:         ], escalus_client:wait_for_stanzas(Alice, 2)),
  392: 
  393:         escalus_client:send(Alice,
  394:             escalus_stanza:privacy_get_lists([<<"someList">>])),
  395: 
  396:         %% Finally ensure that the list doesn't exist anymore.
  397:         escalus_assert:is_privacy_list_nonexistent_error(
  398:             escalus_client:wait_for_stanza(Alice))
  399: 
  400:         end).
  401: 
  402: block_jid_message(Config) ->
  403:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  404: 
  405:         %% Alice should receive message
  406:         escalus_client:send(Bob,
  407:             escalus_stanza:chat_to(Alice, <<"Hi! What's your name?">>)),
  408:         escalus_assert:is_chat_message(<<"Hi! What's your name?">>,
  409:             escalus_client:wait_for_stanza(Alice)),
  410: 
  411:         %% set the list on server and make it active
  412:         privacy_helper:set_and_activate(Alice, {<<"deny_client_message">>, Bob}),
  413: 
  414:         %% Alice should NOT receive message, while Bob gets error message
  415:         escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hi, Alice!">>)),
  416:         privacy_helper:gets_error(Bob, <<"service-unavailable">>),
  417:         timer:sleep(?SLEEP_TIME),
  418:         escalus_assert:has_no_stanzas(Alice),
  419: 
  420:         %% Blocking only applies to incoming messages, so Alice can still send
  421:         %% Bob a message
  422:         %% and Bob gets nothing
  423:         escalus_client:send(Alice, escalus_stanza:chat_to(
  424:                                      Bob, <<"Hi, Bobbb!">>)),
  425:         escalus_assert:is_chat_message(<<"Hi, Bobbb!">>,
  426:                                        escalus_client:wait_for_stanza(Bob))
  427: 
  428:         end).
  429: 
  430: block_group_message(Config) ->
  431:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  432: 
  433:         %% Alice should receive message
  434:         escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hi!">>)),
  435:         escalus_assert:is_chat_message(<<"Hi!">>,
  436:             escalus_client:wait_for_stanza(Alice)),
  437: 
  438:         %% add Bob to Alices' group 'ignored'
  439:         add_sample_contact(Alice, Bob, [<<"ignored">>], <<"Ugly Bastard">>),
  440: 
  441:         %% set the list on server and make it active
  442:         privacy_helper:set_and_activate(Alice, <<"deny_group_message">>),
  443: 
  444:         %% Alice should NOT receive message
  445:         escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hi, blocked group!">>)),
  446:         timer:sleep(?SLEEP_TIME),
  447:         escalus_assert:has_no_stanzas(Alice),
  448:         privacy_helper:gets_error(Bob, <<"service-unavailable">>)
  449: 
  450:         end).
  451: 
  452: block_subscription_message(Config) ->
  453:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  454: 
  455:         %% Alice should receive message
  456:         escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hi!">>)),
  457:         escalus_assert:is_chat_message(<<"Hi!">>,
  458:             escalus_client:wait_for_stanza(Alice)),
  459: 
  460:         %% Alice sends unsubscribe
  461:         Stanza = escalus_stanza:presence_direct(escalus_utils:get_short_jid(Bob),
  462:                                                 <<"unsubscribe">>),
  463:         escalus_client:send(Alice, Stanza),
  464: 
  465:         %% set the list on server and make it active
  466:         privacy_helper:set_and_activate(Alice, <<"deny_unsubscribed_message">>),
  467: 
  468:         %% Alice should NOT receive message
  469:         escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hi!">>)),
  470:         timer:sleep(?SLEEP_TIME),
  471:         escalus_assert:has_no_stanzas(Alice),
  472:         privacy_helper:gets_error(Bob, <<"service-unavailable">>)
  473: 
  474:         end).
  475: 
  476: allow_subscription_to_from_message(Config) ->
  477:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  478:         %% deny all message but not from subscribed "to"
  479:         privacy_helper:set_and_activate(Alice, <<"deny_all_message_but_subscription_to">>),
  480: 
  481:         %% deny all message but not from subscribed "from"
  482:         privacy_helper:set_and_activate(Bob, <<"deny_all_message_but_subscription_from">>),
  483: 
  484:         %% Bob and Alice cannot sent to each other now
  485:         escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hi, Alice XYZ!">>)),
  486:         escalus_client:send(Alice, escalus_stanza:chat_to(Bob, <<"Hi, Bob XYZ!">>)),
  487: 
  488:         ct:sleep(?SLEEP_TIME),
  489:         %% they received just rejection msgs
  490:         privacy_helper:gets_error(Alice, <<"service-unavailable">>),
  491:         escalus_assert:has_no_stanzas(Alice),
  492:         privacy_helper:gets_error(Bob, <<"service-unavailable">>),
  493:         escalus_assert:has_no_stanzas(Bob),
  494: 
  495:         %% Alice subscribes to Bob
  496:         subscribe_from_to(Alice, Bob, false),
  497: 
  498:         %% Now Alice is subscribed "to" Bob
  499:         %% And Bob is subscribed "from" Alice
  500: 
  501:         escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hi, Alice XYZ!">>)),
  502:         escalus_assert:is_chat_message(<<"Hi, Alice XYZ!">>,
  503:                                        escalus_client:wait_for_stanza(Alice)),
  504: 
  505:         escalus_client:send(Alice, escalus_stanza:chat_to(Bob, <<"Hi, Bob XYZ!">>)),
  506:         escalus_assert:is_chat_message(<<"Hi, Bob XYZ!">>,
  507:                                        escalus_client:wait_for_stanza(Bob))
  508: 
  509:     end).
  510: 
  511: allow_subscription_both_message(Config) ->
  512:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  513: 
  514:         %% Alice subscribes to Bob
  515:         subscribe_from_to(Alice, Bob, false),
  516: 
  517:         %% deny all message but not from subscribed "to"
  518:         privacy_helper:set_and_activate(Alice, <<"deny_all_message_but_subscription_both">>),
  519: 
  520:         %% deny all message but not from subscribed "from"
  521:         privacy_helper:set_and_activate(Bob, <<"deny_all_message_but_subscription_both">>),
  522: 
  523:         %% Bob and Alice cannot write to each other now
  524:         %% Even though they are in subscription "to" and "from" respectively
  525:         escalus_client:send(Bob, escalus_stanza:chat_to(
  526:                                    Alice, <<"Hi, Alice XYZ!">>)),
  527:         escalus_client:send(Alice, escalus_stanza:chat_to(
  528:                                      Bob, <<"Hi, Bob XYZ 1!">>)),
  529: 
  530:         privacy_helper:gets_error(Alice, <<"service-unavailable">>),
  531:         privacy_helper:gets_error(Bob, <<"service-unavailable">>),
  532:         escalus_assert:has_no_stanzas(Alice),
  533:         escalus_assert:has_no_stanzas(Bob),
  534: 
  535:         %% Bob subscribes to Alice
  536:         subscribe_from_to(Bob, Alice, true),
  537: 
  538:         %% Now their subscription is in state "both"
  539:         escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hi, Alice XYZ!">>)),
  540:         escalus_assert:is_chat_message(<<"Hi, Alice XYZ!">>,
  541:                                        escalus_client:wait_for_stanza(Alice)),
  542: 
  543:         escalus_client:send(Alice, escalus_stanza:chat_to(Bob, <<"Hi, Bob XYZ! 2">>)),
  544:         escalus_assert:is_chat_message(<<"Hi, Bob XYZ! 2">>,
  545:                                        escalus_client:wait_for_stanza(Bob))
  546: 
  547:     end).
  548: 
  549: block_all_message(Config) ->
  550:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  551: 
  552:         %% Alice should receive message
  553:         escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hi!">>)),
  554:         escalus_assert:is_chat_message(<<"Hi!">>,
  555:                                        escalus_client:wait_for_stanza(Alice)),
  556: 
  557:         %% set the list on server and make it active
  558:         privacy_helper:set_and_activate(Alice, <<"deny_all_message">>),
  559: 
  560:         %% Alice should NOT receive message
  561:         escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hi!">>)),
  562:         timer:sleep(?SLEEP_TIME),
  563:         escalus_assert:has_no_stanzas(Alice),
  564:         privacy_helper:gets_error(Bob, <<"service-unavailable">>)
  565: 
  566:         end).
  567: 
  568: block_jid_presence_in(Config) ->
  569:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  570: 
  571:         %% Alice should receive presence in
  572:         Presence1 =  escalus_stanza:presence_direct(escalus_utils:get_short_jid(Alice),
  573:                                                     <<"available">>),
  574:         escalus_client:send(Bob, Presence1),
  575:         Received = escalus_client:wait_for_stanza(Alice),
  576:         escalus:assert(is_presence, Received),
  577:         escalus_assert:is_stanza_from(Bob, Received),
  578: 
  579:         privacy_helper:set_and_activate(Alice, {<<"deny_client_presence_in">>, Bob}),
  580: 
  581:         %% Alice should NOT receive presence in
  582:         Presence2 = escalus_stanza:presence_direct(escalus_utils:get_short_jid(Alice),
  583:                                                    <<"available">>),
  584:         escalus_client:send(Bob, Presence2),
  585:         timer:sleep(?SLEEP_TIME),
  586:         escalus_assert:has_no_stanzas(Alice),
  587:         %% and Bob should NOT receive any response
  588:         escalus_assert:has_no_stanzas(Bob)
  589: 
  590: 
  591:         end).
  592: 
  593: block_jid_presence_out(Config) ->
  594:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  595: 
  596:         BobBareJID = escalus_utils:get_short_jid(Bob),
  597: 
  598:         %% Bob should receive presence in
  599:         Presence1 = escalus_stanza:presence_direct(BobBareJID, <<"available">>),
  600:         escalus_client:send(Alice, Presence1),
  601: 
  602:         Received = escalus_client:wait_for_stanza(Bob),
  603:         escalus:assert(is_presence, Received),
  604:         escalus_assert:is_stanza_from(Alice, Received),
  605: 
  606:         privacy_helper:set_and_activate(Alice, {<<"deny_client_presence_out">>, Bob}),
  607: 
  608:         %% Bob should NOT receive presence in
  609:         Presence2 = escalus_stanza:presence_direct(BobBareJID, <<"available">>),
  610:         escalus_client:send(Alice, Presence2),
  611: 
  612:         %% Alice gets an error back from mod_privacy
  613:         ErrorPresence = escalus_client:wait_for_stanza(Alice),
  614:         escalus:assert(is_presence_with_type, [<<"error">>], ErrorPresence),
  615: 
  616:         timer:sleep(?SLEEP_TIME),
  617:         escalus_assert:has_no_stanzas(Bob)
  618: 
  619:         end).
  620: 
  621: version_iq(Type, From, To) ->
  622:     Req = escalus_stanza:iq(Type, [escalus_stanza:query_el(<<"jabber:iq:version">>, [])]),
  623:     Req1 = escalus_stanza:to(Req, To),
  624:     Req2= escalus_stanza:from(Req1, From),
  625:     Req2.
  626: 
  627: iq_reply_doesnt_crash_user_process(Config) ->
  628:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  629: 
  630:         QueryWithPrivacyNS = escalus_stanza:query_el(?NS_PRIVACY, []),
  631:         %% Send IQ reply with privacy ns
  632:         %% Send message to check user process still alive
  633:         privacy_helper:does_user_process_crash(Alice,
  634:             Bob,
  635:             <<"error">>,
  636:             QueryWithPrivacyNS,
  637:             <<"Hello, Bob">>),
  638: 
  639:         privacy_helper:does_user_process_crash(Bob,
  640:             Alice,
  641:             <<"result">>,
  642:             QueryWithPrivacyNS,
  643:             <<"Hello, Alice">>)
  644:     end).
  645: 
  646: block_jid_iq(Config) ->
  647:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  648: 
  649:         LServer = escalus_utils:get_server(Bob),
  650:         privacy_helper:set_list(Alice, {<<"deny_server_iq">>, LServer}),
  651:         %% activate it
  652:         Stanza = escalus_stanza:privacy_activate(<<"deny_server_iq">>),
  653:         escalus_client:send(Alice, Stanza),
  654:         timer:sleep(500), %% we must let it sink in
  655: 
  656:         %% bob queries for version and gets an error, Alice doesn't receive the query
  657:         escalus_client:send(Bob, version_iq(<<"get">>, Bob, Alice)),
  658:         timer:sleep(?SLEEP_TIME),
  659:         escalus_assert:has_no_stanzas(Alice),
  660:         privacy_helper:gets_error(Bob, <<"service-unavailable">>),
  661:         %% this stanza does not make much sense, but is routed and rejected correctly
  662:         escalus_client:send(Bob, version_iq(<<"set">>, Bob, Alice)),
  663:         timer:sleep(?SLEEP_TIME),
  664:         escalus_assert:has_no_stanzas(Alice),
  665:         privacy_helper:gets_error(Bob, <<"service-unavailable">>),
  666:         %% but another type, like result, is silently dropped
  667:         escalus_client:send(Bob, version_iq(<<"result">>, Bob, Alice)),
  668:         timer:sleep(?SLEEP_TIME),
  669:         escalus_assert:has_no_stanzas(Alice),
  670:         escalus_assert:has_no_stanzas(Bob)
  671: 
  672:         end).
  673: 
  674: block_jid_all(Config) ->
  675:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  676: 
  677:         privacy_helper:set_list(Alice, {<<"deny_jid_all">>, Bob}),
  678: 
  679:         %% Alice blocks Bob
  680:         Stanza = escalus_stanza:privacy_activate(<<"deny_jid_all">>),
  681:         escalus_client:send(Alice, Stanza),
  682: 
  683:         %% IQ response is blocked;
  684:         %% do magic wait for the request to take effect
  685:         timer:sleep(200),
  686: 
  687:         %% From now on nothing whatsoever sent by Bob should reach Alice.
  688: 
  689:         %% Alice should NOT receive message, Bob receives err msg
  690:         escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hi!">>)),
  691:         privacy_helper:gets_error(Bob, <<"service-unavailable">>),
  692: 
  693:         %% Alice should NOT receive presence-in from Bob, no err msg
  694:         AliceBareJID = escalus_utils:get_short_jid(Alice),
  695:         Presence1 = escalus_stanza:presence_direct(AliceBareJID,
  696:                                                    <<"available">>),
  697:         escalus_client:send(Bob, Presence1),
  698:         timer:sleep(?SLEEP_TIME),
  699:         escalus_assert:has_no_stanzas(Bob),
  700: 
  701:         %% Bob should NOT receive presence-in from Alice, Alice receives err msg
  702:         BobBareJID = escalus_utils:get_short_jid(Bob),
  703:         Presence2 = escalus_stanza:presence_direct(BobBareJID, <<"available">>),
  704:         escalus_client:send(Alice, Presence2),
  705:         timer:sleep(?SLEEP_TIME),
  706:         privacy_helper:gets_error(Alice, <<"not-acceptable">>),
  707: 
  708:         %% Just set the toy list and en~sure that only
  709:         %% the notification push comes back.
  710:         privacy_helper:send_set_list(Alice, {<<"deny_client">>, Bob}),
  711: 
  712:         %% verify
  713:         timer:sleep(?SLEEP_TIME),
  714:         %% ...that nothing else reached Bob
  715:         escalus_assert:has_no_stanzas(Bob),
  716:         %% ...that Alice got a privacy push
  717:         Responses = escalus_client:wait_for_stanza(Alice),
  718:         escalus:assert(fun privacy_helper:is_privacy_list_push/1, Responses),
  719:         %% and Alice didn't get anything else
  720:         escalus_assert:has_no_stanzas(Alice)
  721: 
  722:         end).
  723: 
  724: block_jid_message_but_not_presence(Config) ->
  725:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  726: 
  727:         %% Alice should receive message
  728:         Msg =  escalus_stanza:chat_to(Alice, <<"Hi! What's your name?">>),
  729:         escalus_client:send(Bob, Msg),
  730:         escalus_assert:is_chat_message(<<"Hi! What's your name?">>,
  731:                                        escalus_client:wait_for_stanza(Alice)),
  732: 
  733:         %% set the list on server and make it active
  734:         privacy_helper:set_and_activate(Alice, {<<"deny_client_message">>, Bob}),
  735: 
  736:         %% Alice should NOT receive message
  737:         escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hi, Alice!">>)),
  738:         timer:sleep(?SLEEP_TIME),
  739:         escalus_assert:has_no_stanzas(Alice),
  740:         privacy_helper:gets_error(Bob, <<"service-unavailable">>),
  741: 
  742:         %% ...but should receive presence in
  743:         escalus_client:send(Bob,
  744:                             escalus_stanza:presence_direct(Alice, <<"available">>)),
  745:         Received = escalus_client:wait_for_stanza(Alice),
  746:         escalus:assert(is_presence, Received),
  747:         escalus_assert:is_stanza_from(Bob, Received)
  748: 
  749:         end).
  750: 
  751: newly_blocked_presense_jid_by_new_list(Config) ->
  752:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  753:         add_sample_contact(Alice, Bob, [<<"My Friends">>], <<"Bobbie">>),
  754:         subscribe(Bob, Alice),
  755: 
  756:         %% Alice gets notification that a roster contact is now subscribed
  757:         escalus:assert(is_roster_set, escalus_client:wait_for_stanza(Alice)),
  758: 
  759:         %% Bob should receive presence in
  760:         Presence = escalus_stanza:presence_direct(escalus_client:short_jid(Bob),
  761:                                                   <<"available">>),
  762:         escalus_client:send(Alice, Presence),
  763:         Received = escalus_client:wait_for_stanza(Bob),
  764:         escalus:assert(is_presence, Received),
  765:         escalus_assert:is_stanza_from(Alice, Received),
  766: 
  767:         privacy_helper:set_list(
  768:           Alice, <<"deny_bob_presence_out">>,
  769:           [escalus_stanza:privacy_list_jid_item(<<"1">>, <<"deny">>,
  770:                                                 escalus_client:short_jid(Bob),
  771:                                                 [<<"presence-out">>])]),
  772:         privacy_helper:activate_list(Alice, <<"deny_bob_presence_out">>),
  773: 
  774:         %% Bob should receive unavailable, per XEP-0016 2.11
  775:         Received2 = escalus_client:wait_for_stanza(Bob),
  776:         escalus:assert(is_presence_with_type, [<<"unavailable">>], Received2),
  777:         escalus_assert:is_stanza_from(Alice, Received2)
  778: 
  779:         end).
  780: 
  781: newly_blocked_presense_jid_by_list_change(Config) ->
  782:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  783:         add_sample_contact(Alice, Bob, [<<"My Friends">>], <<"Bobbie">>),
  784:         subscribe(Bob, Alice),
  785: 
  786:         %% Alice gets notification that a roster contact is now subscribed
  787:         escalus:assert(is_roster_set, escalus_client:wait_for_stanza(Alice)),
  788: 
  789:         %% Alice sets up an initially empty privacy list
  790:         privacy_helper:set_and_activate(Alice, <<"noop_list">>),
  791: 
  792:         %% Bob should receive presence in
  793:         escalus_client:send(Alice,
  794:             escalus_stanza:presence_direct(Bob, <<"available">>)),
  795:         Received = escalus_client:wait_for_stanza(Bob),
  796:         escalus:assert(is_presence, Received),
  797:         escalus_assert:is_stanza_from(Alice, Received),
  798: 
  799:         %% Alice now adds Bob to her currently active privacy list
  800:         privacy_helper:set_list(
  801:           Alice, <<"noop_list">>,
  802:           [escalus_stanza:privacy_list_jid_item(<<"1">>, <<"deny">>,
  803:                                                 escalus_client:short_jid(Bob),
  804:                                                 [<<"presence-out">>])]),
  805: 
  806:         %% Bob should receive unavailable, per XEP-0016 2.11
  807:         Received2 = escalus_client:wait_for_stanza(Bob),
  808:         escalus:assert(is_presence_with_type, [<<"unavailable">>], Received2),
  809:         escalus_assert:is_stanza_from(Alice, Received2)
  810: 
  811:         end).
  812: 
  813: newly_blocked_presence_not_notify_self(Config) ->
  814:     escalus:fresh_story(Config, [{alice, 1}], fun(Alice) ->
  815:         %% Alice sets up an initially empty privacy list
  816:         privacy_helper:set_and_activate(Alice,
  817:                                         <<"deny_not_both_presence_out">>),
  818: 
  819:         %% Alice should not receive an 'unavailable' because she's not a
  820:         %% contact of herself.
  821:         timer:sleep(?SLEEP_TIME),
  822:         escalus_assert:has_no_stanzas(Alice)
  823: 
  824:         end).
  825: 
  826: %%-----------------------------------------------------------------
  827: %% Helpers
  828: %%-----------------------------------------------------------------
  829: 
  830: add_sample_contact(Who, Whom, Groups, Nick) ->
  831:     escalus_client:send(Who,
  832:                         escalus_stanza:roster_add_contact(Whom,
  833:                                                           Groups,
  834:                                                           Nick)),
  835:     Received = escalus_client:wait_for_stanza(Who),
  836:     escalus_assert:is_roster_set(Received),
  837:     escalus_client:send(Who, escalus_stanza:iq_result(Received)),
  838:     escalus:assert(is_iq_result, escalus:wait_for_stanza(Who)).
  839: 
  840: subscribe(Who, Whom) ->
  841:     % 'Who' sends a subscribe request to 'Whom'
  842:     escalus:send(Who, escalus_stanza:presence_direct(
  843:                         escalus_client:short_jid(Whom), <<"subscribe">>)),
  844:     PushReq = escalus:wait_for_stanza(Who),
  845:     escalus:assert(is_roster_set, PushReq),
  846:     escalus:send(Who, escalus_stanza:iq_result(PushReq)),
  847: 
  848:     %% 'Whom' receives subscription request
  849:     Received = escalus:wait_for_stanza(Whom),
  850:     escalus:assert(is_presence_with_type, [<<"subscribe">>], Received),
  851: 
  852:     %% 'Whom' adds new contact to their roster
  853:     escalus:send(Whom, escalus_stanza:roster_add_contact(Who,
  854:                                                         [<<"enemies">>],
  855:                                                         <<"Enemy1">>)),
  856:     PushReq2 = escalus:wait_for_stanza(Whom),
  857:     escalus:assert(is_roster_set, PushReq2),
  858:     escalus:send(Whom, escalus_stanza:iq_result(PushReq2)),
  859:     escalus:assert(is_iq_result, escalus:wait_for_stanza(Whom)),
  860: 
  861:     %% 'Whom' sends subscribed presence
  862:     escalus:send(Whom, escalus_stanza:presence_direct(
  863:                          escalus_client:short_jid(Who), <<"subscribed">>)),
  864: 
  865:     %% 'Who' receives subscribed
  866:     Stanzas = escalus:wait_for_stanzas(Who, 2),
  867: 
  868:     check_subscription_stanzas(Stanzas, <<"subscribed">>),
  869:     escalus:assert(is_presence, escalus:wait_for_stanza(Who)).
  870: 
  871: check_subscription_stanzas(Stanzas, Type) ->
  872:     IsPresWithType = fun(S) ->
  873:                          escalus_pred:is_presence_with_type(Type, S)
  874:                      end,
  875:     escalus:assert_many([is_roster_set, IsPresWithType], Stanzas).
  876: 
  877: subscribe_from_to(From, To, IsSecondSubscription) ->
  878:     %% From subscribes to To
  879:     ToBareJid = escalus_utils:get_short_jid(To),
  880:     SubStanza = escalus_stanza:presence_direct(ToBareJid, <<"subscribe">>),
  881:     escalus_client:send(From, SubStanza),
  882:     PushReq = escalus_client:wait_for_stanza(From),
  883:     escalus:assert(is_roster_set, PushReq),
  884:     Received = escalus_client:wait_for_stanza(To),
  885:     %% To accepts From
  886:     FromBareJid = escalus_utils:get_short_jid(From),
  887:     SubConfirmStanza = escalus_stanza:presence_direct(FromBareJid, <<"subscribed">>),
  888:     escalus_client:send(To, SubConfirmStanza),
  889:     case IsSecondSubscription of
  890:         true ->
  891:             escalus:assert(is_roster_set, Received),
  892:             escalus_client:wait_for_stanzas(To, 2);
  893:         false ->
  894:             escalus:assert(is_presence_with_type, [<<"subscribe">>], Received),
  895:             escalus_client:wait_for_stanza(To)
  896:     end,
  897:     escalus_client:wait_for_stanzas(From, 3).