1: -module(graphql_account_SUITE). 2: 3: -include_lib("eunit/include/eunit.hrl"). 4: -include_lib("common_test/include/ct.hrl"). 5: 6: -compile([export_all, nowarn_export_all]). 7: 8: -import(common_helper, [unprep/1]). 9: -import(distributed_helper, [mim/0, require_rpc_nodes/1, rpc/4]). 10: -import(graphql_helper, [execute_command/4, execute_user_command/5, get_listener_port/1, 11: get_listener_config/1, get_ok_value/2, get_err_msg/1, 12: execute_domain_admin_command/4, get_unauthorized/1, 13: get_coercion_err_msg/1]). 14: 15: -define(NOT_EXISTING_JID, <<"unknown987@unknown">>). 16: -define(NOT_EXISTING_NAME, <<"unknown987@", (domain_helper:domain())/binary>>). 17: -define(EMPTY_NAME_JID, <<"@", (domain_helper:domain())/binary>>). 18: 19: suite() -> 20: require_rpc_nodes([mim]) ++ escalus:suite(). 21: 22: all() -> 23: [{group, user_account}, 24: {group, admin_account_http}, 25: {group, admin_account_cli}, 26: {group, domain_admin_account}]. 27: 28: groups() -> 29: [{user_account, [parallel], user_account_tests()}, 30: {admin_account_http, [], admin_account_tests() ++ admin_account_http_tests()}, 31: {admin_account_cli, [], admin_account_tests() ++ admin_account_cli_tests()}, 32: {domain_admin_account, [], domain_admin_tests()}]. 33: 34: user_account_tests() -> 35: [user_unregister, 36: user_change_password]. 37: 38: admin_account_tests() -> 39: [admin_list_users, 40: admin_list_users_unknown_domain, 41: admin_count_users, 42: admin_count_users_unknown_domain, 43: admin_check_password, 44: admin_check_password_non_existing_user, 45: admin_check_password_hash, 46: admin_check_password_hash_non_existing_user, 47: admin_check_plain_password_hash, 48: admin_check_user, 49: admin_check_non_existing_user, 50: admin_register_user, 51: admin_register_random_user, 52: admin_register_user_non_existing_domain, 53: admin_register_user_limit_error, 54: admin_remove_non_existing_user, 55: admin_remove_existing_user, 56: admin_ban_user, 57: admin_ban_non_existing_user, 58: admin_change_user_password, 59: admin_change_non_existing_user_password]. 60: 61: admin_account_http_tests() -> 62: [admin_import_users_http]. 63: 64: admin_account_cli_tests() -> 65: [admin_import_users_cli]. 66: 67: domain_admin_tests() -> 68: [admin_list_users, 69: domain_admin_list_users_no_permission, 70: admin_count_users, 71: domain_admin_count_users_no_permission, 72: admin_check_password, 73: domain_admin_check_password_no_permission, 74: admin_check_password_hash, 75: domain_admin_check_password_hash_no_permission, 76: domain_admin_check_plain_password_hash_no_permission, 77: admin_check_user, 78: domain_admin_check_user_no_permission, 79: admin_register_user, 80: domain_admin_register_user_no_permission, 81: admin_register_random_user, 82: domain_admin_register_random_user_no_permission, 83: admin_register_user_limit_error, 84: admin_remove_existing_user, 85: domain_admin_remove_user_no_permission, 86: admin_ban_user, 87: domain_admin_ban_user_no_permission, 88: admin_change_user_password, 89: domain_admin_change_user_password_no_permission]. 90: 91: init_per_suite(Config) -> 92: Config1 = [{ctl_auth_mods, mongoose_helper:auth_modules()} | Config], 93: Config2 = escalus:init_per_suite(Config1), 94: Config3 = ejabberd_node_utils:init(mim(), Config2), 95: dynamic_modules:save_modules(domain_helper:host_type(), Config3). 96: 97: end_per_suite(Config) -> 98: file:delete(filename:join(?config(mim_data_dir, Config), "users.csv.tmp")), 99: dynamic_modules:restore_modules(Config), 100: escalus:end_per_suite(Config). 101: 102: init_per_group(admin_account_http, Config) -> 103: graphql_helper:init_admin_handler(init_users(Config)); 104: init_per_group(admin_account_cli, Config) -> 105: graphql_helper:init_admin_cli(init_users(Config)); 106: init_per_group(domain_admin_account, Config) -> 107: graphql_helper:init_domain_admin_handler(domain_admin_init_users(Config)); 108: init_per_group(user_account, Config) -> 109: graphql_helper:init_user(Config). 110: 111: end_per_group(user_account, _Config) -> 112: graphql_helper:clean(), 113: escalus_fresh:clean(); 114: end_per_group(domain_admin_account, Config) -> 115: graphql_helper:clean(), 116: domain_admin_clean_users(Config); 117: end_per_group(_GroupName, Config) -> 118: graphql_helper:clean(), 119: clean_users(Config). 120: 121: init_users(Config) -> 122: escalus:create_users(Config, escalus:get_users([alice])). 123: 124: domain_admin_init_users(Config) -> 125: escalus:create_users(Config, escalus:get_users([alice, alice_bis])). 126: 127: clean_users(Config) -> 128: escalus_fresh:clean(), 129: escalus:delete_users(Config, escalus:get_users([alice])). 130: 131: domain_admin_clean_users(Config) -> 132: escalus_fresh:clean(), 133: escalus:delete_users(Config, escalus:get_users([alice, alice_bis])). 134: 135: init_per_testcase(admin_register_user = C, Config) -> 136: Config1 = [{user, {<<"gql_admin_registration_test">>, domain_helper:domain()}} | Config], 137: escalus:init_per_testcase(C, Config1); 138: init_per_testcase(admin_check_plain_password_hash = C, Config) -> 139: {_, AuthMods} = lists:keyfind(ctl_auth_mods, 1, Config), 140: case lists:member(ejabberd_auth_ldap, AuthMods) of 141: true -> 142: {skip, not_fully_supported_with_ldap}; 143: false -> 144: AuthOpts = mongoose_helper:auth_opts_with_password_format(plain), 145: Config1 = mongoose_helper:backup_and_set_config_option( 146: Config, {auth, domain_helper:host_type()}, AuthOpts), 147: Config2 = escalus:create_users(Config1, escalus:get_users([carol])), 148: escalus:init_per_testcase(C, Config2) 149: end; 150: init_per_testcase(admin_register_user_limit_error = C, Config) -> 151: Domain = domain_helper:domain(), 152: {ok, HostType} = rpc(mim(), mongoose_domain_api, get_domain_host_type, [Domain]), 153: OptKey = [{auth, HostType}, max_users_per_domain], 154: Config1 = mongoose_helper:backup_and_set_config_option(Config, OptKey, 3), 155: Config2 = [{bob, <<"bob">>}, {kate, <<"kate">>}, {john, <<"john">>} | Config1], 156: escalus:init_per_testcase(C, Config2); 157: init_per_testcase(domain_admin_check_plain_password_hash_no_permission = C, Config) -> 158: {_, AuthMods} = lists:keyfind(ctl_auth_mods, 1, Config), 159: case lists:member(ejabberd_auth_ldap, AuthMods) of 160: true -> 161: {skip, not_fully_supported_with_ldap}; 162: false -> 163: AuthOpts = mongoose_helper:auth_opts_with_password_format(plain), 164: Config1 = mongoose_helper:backup_and_set_config_option( 165: Config, {auth, domain_helper:host_type()}, AuthOpts), 166: Config2 = escalus:create_users(Config1, escalus:get_users([alice_bis])), 167: escalus:init_per_testcase(C, Config2) 168: end; 169: init_per_testcase(domain_admin_register_user = C, Config) -> 170: Config1 = [{user, {<<"gql_domain_admin_registration_test">>, domain_helper:domain()}} | Config], 171: escalus:init_per_testcase(C, Config1); 172: init_per_testcase(CaseName, Config) -> 173: escalus:init_per_testcase(CaseName, Config). 174: 175: end_per_testcase(admin_register_user = C, Config) -> 176: {Username, Domain} = proplists:get_value(user, Config), 177: rpc(mim(), mongoose_account_api, unregister_user, [Username, Domain]), 178: escalus:end_per_testcase(C, Config); 179: end_per_testcase(admin_check_plain_password_hash, Config) -> 180: mongoose_helper:restore_config(Config), 181: escalus:delete_users(Config, escalus:get_users([carol])); 182: end_per_testcase(admin_register_user_limit_error = C, Config) -> 183: Domain = domain_helper:domain(), 184: rpc(mim(), mongoose_account_api, unregister_user, [proplists:get_value(bob, Config), Domain]), 185: rpc(mim(), mongoose_account_api, unregister_user, [proplists:get_value(kate, Config), Domain]), 186: rpc(mim(), mongoose_account_api, unregister_user, [proplists:get_value(john, Config), Domain]), 187: mongoose_helper:restore_config(Config), 188: escalus:end_per_testcase(C, Config); 189: end_per_testcase(domain_admin_check_plain_password_hash_no_permission, Config) -> 190: mongoose_helper:restore_config(Config), 191: escalus:delete_users(Config, escalus:get_users([carol, alice_bis])); 192: end_per_testcase(domain_admin_register_user = C, Config) -> 193: {Username, Domain} = proplists:get_value(user, Config), 194: rpc(mim(), mongoose_account_api, unregister_user, [Username, Domain]), 195: escalus:end_per_testcase(C, Config); 196: end_per_testcase(CaseName, Config) 197: when CaseName == admin_import_users_http; CaseName == admin_import_users_cli -> 198: Domain = domain_helper:domain(), 199: rpc(mim(), mongoose_account_api, unregister_user, [<<"john">>, Domain]), 200: escalus:end_per_testcase(CaseName, Config); 201: end_per_testcase(CaseName, Config) -> 202: escalus:end_per_testcase(CaseName, Config). 203: 204: user_unregister(Config) -> 205: escalus:fresh_story_with_config(Config, [{alice, 1}], fun user_unregister_story/2). 206: 207: user_unregister_story(Config, Alice) -> 208: Resp = user_unregister(Alice, Config), 209: Path = [data, account, unregister], 210: ?assertNotEqual(nomatch, binary:match(get_ok_value(Path, Resp), <<"successfully unregistered">>)), 211: % Ensure the user is removed 212: AllUsers = rpc(mim(), mongoose_account_api, list_users, [domain_helper:domain()]), 213: {_, AllUsersList} = AllUsers, 214: LAliceJID = jid:to_binary(jid:from_binary(escalus_client:short_jid(Alice))), 215: ?assertNot(lists:member(LAliceJID, AllUsersList)). 216: 217: user_change_password(Config) -> 218: escalus:fresh_story_with_config(Config, [{alice, 1}], fun user_change_password_story/2). 219: 220: user_change_password_story(Config, Alice) -> 221: % Set an empty password 222: Resp1 = user_change_password(Alice, <<>>, Config), 223: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp1), <<"Empty password">>)), 224: % Set a correct password 225: Resp2 = user_change_password(Alice, <<"kaczka">>, Config), 226: Path = [data, account, changePassword], 227: ?assertNotEqual(nomatch, binary:match(get_ok_value(Path, Resp2), <<"Password changed">>)). 228: 229: admin_list_users(Config) -> 230: Domain = domain_helper:domain(), 231: Username = jid:nameprep(escalus_users:get_username(Config, alice)), 232: JID = <<Username/binary, "@", Domain/binary>>, 233: Resp1 = list_users(Domain, Config), 234: Users = get_ok_value([data, account, listUsers], Resp1), 235: ?assert(lists:member(JID, Users)), 236: Resp2 = list_users(unprep(Domain), Config), 237: ?assertEqual(Users, get_ok_value([data, account, listUsers], Resp2)). 238: 239: admin_list_users_unknown_domain(Config) -> 240: Resp = list_users(<<"unknown-domain">>, Config), 241: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp), <<"Domain does not exist">>)). 242: 243: admin_count_users(Config) -> 244: % A domain with at least one user 245: Domain = domain_helper:domain(), 246: Resp1 = count_users(Domain, Config), 247: Count = get_ok_value([data, account, countUsers], Resp1), 248: ?assert(0 < Count), 249: Resp2 = count_users(unprep(Domain), Config), 250: ?assertEqual(Count, get_ok_value([data, account, countUsers], Resp2)). 251: 252: admin_count_users_unknown_domain(Config) -> 253: Resp = count_users(<<"unknown-domain">>, Config), 254: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp), <<"Domain does not exist">>)). 255: 256: admin_check_password(Config) -> 257: Password = lists:last(escalus_users:get_usp(Config, alice)), 258: BinJID = escalus_users:get_jid(Config, alice), 259: Path = [data, account, checkPassword], 260: % A correct password 261: Resp1 = check_password(BinJID, Password, Config), 262: ?assertMatch(#{<<"correct">> := true, <<"message">> := _}, get_ok_value(Path, Resp1)), 263: % An incorrect password 264: Resp2 = check_password(BinJID, <<"incorrect_pw">>, Config), 265: ?assertMatch(#{<<"correct">> := false, <<"message">> := _}, get_ok_value(Path, Resp2)). 266: 267: admin_check_password_non_existing_user(Config) -> 268: Password = lists:last(escalus_users:get_usp(Config, alice)), 269: % Non-existing user, non-existing domain 270: Resp = check_password(?NOT_EXISTING_JID, Password, Config), 271: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp), <<"not exist">>)), 272: % Non-existing user, existing domain 273: Resp2 = check_password(?NOT_EXISTING_NAME, Password, Config), 274: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp2), <<"not exist">>)), 275: % Empty username 276: Resp3 = check_password(?EMPTY_NAME_JID, Password, Config), 277: get_coercion_err_msg(Resp3). 278: 279: admin_check_password_hash(Config) -> 280: UserSCRAM = escalus_users:get_jid(Config, alice), 281: EmptyHash = list_to_binary(get_md5(<<>>)), 282: Method = <<"md5">>, 283: % SCRAM password user 284: Resp1 = check_password_hash(UserSCRAM, EmptyHash, Method, Config), 285: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp1), <<"SCRAM password">>)). 286: 287: admin_check_password_hash_non_existing_user(Config) -> 288: EmptyHash = list_to_binary(get_md5(<<>>)), 289: Method = <<"md5">>, 290: % Non-existing user, non-existing domain 291: Resp = check_password_hash(?NOT_EXISTING_JID, EmptyHash, Method, Config), 292: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp), <<"not exist">>)), 293: % Non-existing user, existing domain 294: Resp2 = check_password_hash(?NOT_EXISTING_NAME, EmptyHash, Method, Config), 295: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp2), <<"not exist">>)), 296: % Empty username 297: Resp3 = check_password_hash(?EMPTY_NAME_JID, EmptyHash, Method, Config), 298: get_coercion_err_msg(Resp3). 299: 300: admin_check_plain_password_hash(Config) -> 301: UserJID = escalus_users:get_jid(Config, carol), 302: Password = lists:last(escalus_users:get_usp(Config, carol)), 303: Method = <<"md5">>, 304: Hash = list_to_binary(get_md5(Password)), 305: WrongHash = list_to_binary(get_md5(<<"wrong password">>)), 306: Path = [data, account, checkPasswordHash], 307: % A correct hash 308: Resp = check_password_hash(UserJID, Hash, Method, Config), 309: ?assertMatch(#{<<"correct">> := true, <<"message">> := _}, get_ok_value(Path, Resp)), 310: % An incorrect hash 311: Resp2 = check_password_hash(UserJID, WrongHash, Method, Config), 312: ?assertMatch(#{<<"correct">> := false, <<"message">> := _}, get_ok_value(Path, Resp2)), 313: % A not-supported hash method 314: Resp3 = check_password_hash(UserJID, Hash, <<"a">>, Config), 315: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp3), <<"not supported">>)). 316: 317: admin_check_user(Config) -> 318: BinJID = escalus_users:get_jid(Config, alice), 319: Path = [data, account, checkUser], 320: Resp = check_user(BinJID, Config), 321: ?assertMatch(#{<<"exist">> := true, <<"message">> := _}, get_ok_value(Path, Resp)). 322: 323: admin_check_non_existing_user(Config) -> 324: Path = [data, account, checkUser], 325: % Non-existing user, non-existing domain 326: Resp = check_user(?NOT_EXISTING_JID, Config), 327: ?assertMatch(#{<<"exist">> := false, <<"message">> := _}, get_ok_value(Path, Resp)), 328: % Non-existing user, existing domain 329: Resp2 = check_user(?NOT_EXISTING_NAME, Config), 330: ?assertMatch(#{<<"exist">> := false, <<"message">> := _}, get_ok_value(Path, Resp2)), 331: % Empty username 332: Resp3 = check_user(?EMPTY_NAME_JID, Config), 333: get_coercion_err_msg(Resp3). 334: 335: admin_register_user(Config) -> 336: Password = <<"my_password">>, 337: {Username, Domain} = proplists:get_value(user, Config), 338: Path = [data, account, registerUser, message], 339: % Register a new user 340: Resp1 = register_user(Domain, Username, Password, Config), 341: ?assertNotEqual(nomatch, binary:match(get_ok_value(Path, Resp1), <<"successfully registered">>)), 342: % Try to register a user with existing name 343: Resp2 = register_user(Domain, Username, Password, Config), 344: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp2), <<"already registered">>)), 345: % Try again, this time with a name that is not stringprepped 346: Resp3 = register_user(unprep(Domain), unprep(Username), Password, Config), 347: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp3), <<"already registered">>)), 348: % Try to register a user without any name 349: Resp4 = register_user(Domain, <<>>, Password, Config), 350: ?assertMatch({_, _}, binary:match(get_coercion_err_msg(Resp4), <<"empty_user_name">>)), 351: % Try to register a user with an invalid name 352: Resp5 = register_user(Domain, <<"@invalid">>, Password, Config), 353: ?assertMatch({_, _}, binary:match(get_coercion_err_msg(Resp5), <<"failed_to_parse_user_name">>)). 354: 355: admin_register_random_user(Config) -> 356: Password = <<"my_password">>, 357: Domain = domain_helper:domain(), 358: Path = [data, account, registerUser], 359: % Register a new user 360: Resp1 = register_random_user(Domain, Password, Config), 361: #{<<"message">> := Msg, <<"jid">> := JID} = get_ok_value(Path, Resp1), 362: {Username, Server} = jid:to_lus(jid:from_binary(JID)), 363: 364: ?assertNotEqual(nomatch, binary:match(Msg, <<"successfully registered">>)), 365: {ok, _} = rpc(mim(), mongoose_account_api, unregister_user, [Username, Server]). 366: 367: admin_register_user_non_existing_domain(Config) -> 368: % Try to register a user with a non-existing domain 369: Resp = register_user(<<"unknown">>, <<"alice">>, <<"test_password">>, Config), 370: ?assertMatch({_, _}, binary:match(get_err_msg(Resp), <<"not_allowed">>)). 371: 372: admin_register_user_limit_error(Config) -> 373: Password = <<"password">>, 374: Domain = domain_helper:domain(), 375: Path = [data, account, registerUser, message], 376: Resp1 = register_user(Domain, proplists:get_value(bob, Config), Password, Config), 377: ?assertNotEqual(nomatch, binary:match(get_ok_value(Path, Resp1), <<"successfully registered">>)), 378: Resp2 = register_user(Domain, proplists:get_value(kate, Config), Password, Config), 379: ?assertNotEqual(nomatch, binary:match(get_ok_value(Path, Resp2), <<"successfully registered">>)), 380: %% One user was registered in the init_per_group, and two more were registered in this test case 381: %% There are three registered users at this moment 382: %% The next (fourth) registration should exceed the limit of three 383: JohnNick = proplists:get_value(john, Config), 384: Resp3 = register_user(Domain, JohnNick, Password, Config), 385: ?assertMatch({_, _}, binary:match(get_err_msg(Resp3), <<"limit has been exceeded">>)), 386: %% Make sure the fourth account wasn't created 387: CheckUserPath = [data, account, checkUser], 388: Resp4 = check_user(<<JohnNick/binary, "@", Domain/binary>>, Config), 389: ?assertMatch(#{<<"exist">> := false, <<"message">> := _}, get_ok_value(CheckUserPath, Resp4)). 390: 391: admin_remove_non_existing_user(Config) -> 392: % Non-existing user, non-existing domain 393: Resp = remove_user(?NOT_EXISTING_JID, Config), 394: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp), <<"not exist">>)), 395: % Non-existing user, existing domain 396: Resp2 = remove_user(?NOT_EXISTING_NAME, Config), 397: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp2), <<"not exist">>)), 398: % Empty username 399: Resp3 = remove_user(?EMPTY_NAME_JID, Config), 400: get_coercion_err_msg(Resp3). 401: 402: admin_remove_existing_user(Config) -> 403: escalus:fresh_story(Config, [{alice, 1}], fun(Alice) -> 404: Path = [data, account, removeUser, message], 405: BinJID = escalus_client:full_jid(Alice), 406: Resp4 = remove_user(BinJID, Config), 407: ?assertNotEqual(nomatch, binary:match(get_ok_value(Path, Resp4), 408: <<"successfully unregister">>)) 409: end). 410: 411: admin_ban_user(Config) -> 412: Path = [data, account, banUser, message], 413: Reason = <<"annoying">>, 414: % Ban an existing user 415: escalus:fresh_story(Config, [{alice, 1}], fun(Alice) -> 416: BinJID = escalus_client:full_jid(Alice), 417: Resp1 = ban_user(BinJID, Reason, Config), 418: ?assertNotEqual(nomatch, binary:match(get_ok_value(Path, Resp1), <<"successfully banned">>)) 419: end). 420: 421: admin_ban_non_existing_user(Config) -> 422: Reason = <<"annoying">>, 423: % Non-existing name, non-existing domain 424: Resp = ban_user(?NOT_EXISTING_JID, Reason, Config), 425: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp), <<"not exist">>)), 426: % Non-existing name, existing domain 427: Resp2 = ban_user(?NOT_EXISTING_NAME, Reason, Config), 428: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp2), <<"not exist">>)), 429: % Empty username 430: Resp3 = ban_user(?EMPTY_NAME_JID, Reason, Config), 431: get_coercion_err_msg(Resp3). 432: 433: admin_change_user_password(Config) -> 434: Path = [data, account, changeUserPassword, message], 435: NewPassword = <<"new password">>, 436: escalus:fresh_story(Config, [{alice, 1}], fun(Alice) -> 437: BinJID = escalus_client:full_jid(Alice), 438: % Set an empty password 439: Resp1 = change_user_password(BinJID, <<>>, Config), 440: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp1), <<"Empty password">>)), 441: % Set non-empty password 442: Resp2 = change_user_password(BinJID, NewPassword, Config), 443: ?assertNotEqual(nomatch, binary:match(get_ok_value(Path, Resp2), <<"Password changed">>)) 444: end). 445: 446: admin_change_non_existing_user_password(Config) -> 447: NewPassword = <<"new password">>, 448: % Non-existing name, non-existing domain 449: Resp = change_user_password(?NOT_EXISTING_JID, NewPassword, Config), 450: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp), <<"does not exist">>)), 451: % Non-existing name, existing domain 452: Resp2 = change_user_password(?NOT_EXISTING_NAME, NewPassword, Config), 453: ?assertNotEqual(nomatch, binary:match(get_err_msg(Resp2), <<"does not exist">>)), 454: % Empty username 455: Resp3 = ban_user(?EMPTY_NAME_JID, NewPassword, Config), 456: get_coercion_err_msg(Resp3). 457: 458: admin_import_users_cli(Config) -> 459: escalus:fresh_story(Config, [{alice, 1}], fun(_Alice) -> 460: % Non-existing file 461: Resp = import_users(<<"nonexisting.csv">>, Config), 462: ?assertEqual(<<"File not found">>, get_err_msg(Resp)), 463: % Summary 464: Path = filename:join(?config(mim_data_dir, Config), "users.csv"), 465: Path2 = replace_hosts_in_file(Path), 466: Resp2 = import_users(list_to_binary(Path2), Config), 467: Domain = domain_helper:domain(), 468: ?assertEqual(#{<<"status">> => <<"Completed">>, 469: <<"created">> => [<<"john@", Domain/binary>>], 470: <<"emptyPassword">> => [<<"elise@", Domain/binary>>], 471: <<"existing">> => [<<"alice@", Domain/binary>>], 472: <<"invalidJID">> => [<<",", Domain/binary, ",password">>], 473: <<"invalidRecord">> => [<<"elise,elise,", Domain/binary, ",esile">>], 474: <<"notAllowed">> => null}, 475: get_ok_value([data, account, importUsers], Resp2)) 476: end). 477: 478: admin_import_users_http(Config) -> 479: escalus:fresh_story(Config, [{alice, 1}], fun(_Alice) -> 480: % Summary 481: Path = filename:join(?config(mim_data_dir, Config), "users.csv"), 482: Path2 = replace_hosts_in_file(Path), 483: Resp2 = import_users(list_to_binary(Path2), Config), 484: ?assertEqual(#{<<"status">> => <<"ImportUsers scheduled">>, 485: <<"created">> => null, 486: <<"emptyPassword">> => null, 487: <<"existing">> => null, 488: <<"invalidJID">> => null, 489: <<"invalidRecord">> => null, 490: <<"notAllowed">> => null}, 491: get_ok_value([data, account, importUsers], Resp2)), 492: Domain = domain_helper:domain(), 493: mongoose_helper:wait_until(fun() -> 494: rpc(mim(), mongoose_account_api, check_account, [<<"john">>, Domain]) 495: end, 496: {ok, io_lib:format("User ~s exists", [<<"john@", Domain/binary>>])}, 497: #{time_left => timer:seconds(20), 498: sleep_time => 1000, 499: name => verify_account_created}) 500: end). 501: 502: replace_hosts_in_file(Path) -> 503: {ok, Content} = file:read_file(Path), 504: Content2 = binary:replace(Content, <<"$host$">>, domain_helper:domain(), [global]), 505: Path2 = Path ++ ".tmp", 506: ok = file:write_file(Path2, Content2), 507: Path2. 508: 509: domain_admin_list_users_no_permission(Config) -> 510: % An unknown domain 511: Resp1 = list_users(<<"unknown-domain">>, Config), 512: get_unauthorized(Resp1), 513: % An external domain 514: Resp2 = list_users(domain_helper:secondary_domain(), Config), 515: get_unauthorized(Resp2). 516: 517: domain_admin_count_users_no_permission(Config) -> 518: % An unknown domain 519: Resp1 = count_users(<<"unknown-domain">>, Config), 520: get_unauthorized(Resp1), 521: % An external domain 522: Resp2 = count_users(domain_helper:secondary_domain(), Config), 523: get_unauthorized(Resp2). 524: 525: domain_admin_check_password_no_permission(Config) -> 526: Password = lists:last(escalus_users:get_usp(Config, alice)), 527: PasswordOutside = lists:last(escalus_users:get_usp(Config, alice_bis)), 528: BinOutsideJID = escalus_users:get_jid(Config, alice_bis), 529: % An external domain user 530: Resp3 = check_password(BinOutsideJID, PasswordOutside, Config), 531: get_unauthorized(Resp3), 532: % A non-existing user 533: Resp4 = check_password(?NOT_EXISTING_JID, Password, Config), 534: get_unauthorized(Resp4). 535: 536: domain_admin_check_password_hash_no_permission(Config) -> 537: ExternalUserSCRAM = escalus_users:get_jid(Config, alice_bis), 538: EmptyHash = list_to_binary(get_md5(<<>>)), 539: Method = <<"md5">>, 540: % An external domain user 541: Resp1 = check_password_hash(ExternalUserSCRAM, EmptyHash, Method, Config), 542: get_unauthorized(Resp1), 543: % A non-existing user 544: Resp2 = check_password_hash(?NOT_EXISTING_JID, EmptyHash, Method, Config), 545: get_unauthorized(Resp2). 546: 547: domain_admin_check_plain_password_hash_no_permission(Config) -> 548: Method = <<"md5">>, 549: ExternalUserJID = escalus_users:get_jid(Config, alice_bis), 550: ExternalPassword = lists:last(escalus_users:get_usp(Config, alice_bis)), 551: ExternalHash = list_to_binary(get_md5(ExternalPassword)), 552: get_unauthorized(check_password_hash(ExternalUserJID, ExternalHash, Method, Config)). 553: 554: domain_admin_check_user_no_permission(Config) -> 555: ExternalBinJID = escalus_users:get_jid(Config, alice_bis), 556: % An external domain user 557: Resp1 = check_user(ExternalBinJID, Config), 558: get_unauthorized(Resp1), 559: % A non-existing user 560: Resp2 = check_user(?NOT_EXISTING_JID, Config), 561: get_unauthorized(Resp2). 562: 563: domain_admin_register_user_no_permission(Config) -> 564: Password = <<"my_password">>, 565: Domain = <<"unknown-domain">>, 566: get_unauthorized(register_user(Domain, external_user, Password, Config)). 567: 568: domain_admin_register_random_user_no_permission(Config) -> 569: Password = <<"my_password">>, 570: Domain = domain_helper:secondary_domain(), 571: Resp = register_random_user(Domain, Password, Config), 572: get_unauthorized(Resp). 573: 574: domain_admin_remove_user_no_permission(Config) -> 575: get_unauthorized(remove_user(?NOT_EXISTING_JID, Config)), 576: escalus:fresh_story(Config, [{alice_bis, 1}], fun(AliceBis) -> 577: BinJID = escalus_client:full_jid(AliceBis), 578: get_unauthorized(remove_user(BinJID, Config)) 579: end). 580: 581: domain_admin_ban_user_no_permission(Config) -> 582: Reason = <<"annoying">>, 583: % Ban not existing user 584: Resp1 = ban_user(?NOT_EXISTING_JID, Reason, Config), 585: get_unauthorized(Resp1), 586: % Ban an external domain user 587: escalus:fresh_story(Config, [{alice_bis, 1}], fun(AliceBis) -> 588: BinJID = escalus_client:full_jid(AliceBis), 589: Resp2 = ban_user(BinJID, Reason, Config), 590: get_unauthorized(Resp2) 591: end). 592: 593: domain_admin_change_user_password_no_permission(Config) -> 594: NewPassword = <<"new password">>, 595: % Change password of not existing user 596: Resp1 = change_user_password(?NOT_EXISTING_JID, NewPassword, Config), 597: get_unauthorized(Resp1), 598: % Change external domain user password 599: escalus:fresh_story(Config, [{alice_bis, 1}], fun(AliceBis) -> 600: BinJID = escalus_client:full_jid(AliceBis), 601: Resp2 = change_user_password(BinJID, NewPassword, Config), 602: get_unauthorized(Resp2) 603: end). 604: 605: %% Helpers 606: 607: get_md5(AccountPass) -> 608: lists:flatten([io_lib:format("~.16B", [X]) 609: || X <- binary_to_list(crypto:hash(md5, AccountPass))]). 610: 611: %% Commands 612: 613: user_unregister(User, Config) -> 614: execute_user_command(<<"account">>, <<"unregister">>, User, #{}, Config). 615: 616: user_change_password(User, Password, Config) -> 617: Vars = #{<<"newPassword">> => Password}, 618: execute_user_command(<<"account">>, <<"changePassword">>, User, Vars, Config). 619: 620: list_users(Domain, Config) -> 621: Vars = #{<<"domain">> => Domain}, 622: execute_command(<<"account">>, <<"listUsers">>, Vars, Config). 623: 624: count_users(Domain, Config) -> 625: Vars = #{<<"domain">> => Domain}, 626: execute_command(<<"account">>, <<"countUsers">>, Vars, Config). 627: 628: check_password(User, Password, Config) -> 629: Vars = #{<<"user">> => User, <<"password">> => Password}, 630: execute_command(<<"account">>, <<"checkPassword">>, Vars, Config). 631: 632: check_password_hash(User, PasswordHash, HashMethod, Config) -> 633: Vars = #{<<"user">> => User, <<"passwordHash">> => PasswordHash, <<"hashMethod">> => HashMethod}, 634: execute_command(<<"account">>, <<"checkPasswordHash">>, Vars, Config). 635: 636: check_user(User, Config) -> 637: Vars = #{<<"user">> => User}, 638: execute_command(<<"account">>, <<"checkUser">>, Vars, Config). 639: 640: register_user(Domain, Username, Password, Config) -> 641: Vars = #{<<"domain">> => Domain, <<"username">> => Username, <<"password">> => Password}, 642: execute_command(<<"account">>, <<"registerUser">>, Vars, Config). 643: 644: register_random_user(Domain, Password, Config) -> 645: Vars = #{<<"domain">> => Domain, <<"password">> => Password}, 646: execute_command(<<"account">>, <<"registerUser">>, Vars, Config). 647: 648: remove_user(User, Config) -> 649: Vars = #{<<"user">> => User}, 650: execute_command(<<"account">>, <<"removeUser">>, Vars, Config). 651: 652: ban_user(JID, Reason, Config) -> 653: Vars = #{<<"user">> => JID, <<"reason">> => Reason}, 654: execute_command(<<"account">>, <<"banUser">>, Vars, Config). 655: 656: change_user_password(JID, NewPassword, Config) -> 657: Vars = #{<<"user">> => JID, <<"newPassword">> => NewPassword}, 658: execute_command(<<"account">>, <<"changeUserPassword">>, Vars, Config). 659: 660: import_users(Filename, Config) -> 661: Vars = #{<<"filename">> => Filename}, 662: execute_command(<<"account">>, <<"importUsers">>, Vars, Config).