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