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