File indexing completed on 2024-12-01 04:35:23
0001 /* 0002 0003 * SPDX-FileCopyrightText: 2020 Alessandro Ambrosano <alessandro.ambrosano@gmail.com> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 * 0007 */ 0008 0009 #include "ddpauthenticationmanagertest.h" 0010 0011 #include "rocketchataccount.h" 0012 #include "utils.h" 0013 0014 #include "ddpapi/ddpauthenticationmanager.h" 0015 0016 #include <QSignalSpy> 0017 #include <QTest> 0018 0019 QTEST_GUILESS_MAIN(DDPAuthenticationManagerTest) 0020 0021 DDPAuthenticationManagerTest::DDPAuthenticationManagerTest(QObject *parent) 0022 : QObject(parent) 0023 { 0024 } 0025 0026 void DDPAuthenticationManagerTest::testLoginSuccess() 0027 { 0028 // Logging in with an existing token 0029 { 0030 RocketChatAccount dummyAccount; 0031 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0032 0033 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0034 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0035 authManager.setAuthToken(QStringLiteral("some token")); 0036 authManager.login(); 0037 QCOMPARE(spyStatusChanged.count(), 1); 0038 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0039 0040 authManager.processMethodResponse(0, 0041 Utils::strToJsonObject(QStringLiteral( 0042 R"( 0043 { 0044 "msg": "result", 0045 "id": "0", 0046 "result": { 0047 "id": "some id", 0048 "token": "some token", 0049 "tokenExpires": { 0050 "$date": 1590844250110 0051 }, 0052 "type": "resume" 0053 } 0054 })"))); 0055 0056 QCOMPARE(spyStatusChanged.count(), 2); 0057 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoggedIn); 0058 QCOMPARE(authManager.userId(), QStringLiteral("some id")); 0059 QCOMPARE(authManager.authToken(), QStringLiteral("some token")); 0060 } 0061 0062 // Logging in with username and password 0063 { 0064 RocketChatAccount dummyAccount; 0065 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0066 0067 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0068 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0069 authManager.login(QStringLiteral("someuser"), QStringLiteral("somepassword")); 0070 QCOMPARE(spyStatusChanged.count(), 1); 0071 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0072 0073 authManager.processMethodResponse(0, 0074 Utils::strToJsonObject(QStringLiteral( 0075 R"( 0076 { 0077 "msg": "result", 0078 "id": "0", 0079 "result": { 0080 "id": "some id", 0081 "token": "some token", 0082 "tokenExpires": { 0083 "$date": 1590844250110 0084 }, 0085 "type": "?????" 0086 } 0087 })"))); // TODO: check the type for non-ldap, non-2fa successful login messages 0088 0089 QCOMPARE(spyStatusChanged.count(), 2); 0090 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoggedIn); 0091 QCOMPARE(authManager.userId(), QStringLiteral("some id")); 0092 QCOMPARE(authManager.authToken(), QStringLiteral("some token")); 0093 } 0094 0095 // Logging in using oauth 0096 { 0097 RocketChatAccount dummyAccount; 0098 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0099 0100 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0101 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0102 authManager.loginOAuth(QStringLiteral("someuser"), QStringLiteral("somepassword")); 0103 QCOMPARE(spyStatusChanged.count(), 1); 0104 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0105 0106 authManager.processMethodResponse(0, 0107 Utils::strToJsonObject(QStringLiteral( 0108 R"( 0109 { 0110 "msg": "result", 0111 "id": "0", 0112 "result": { 0113 "id": "some id", 0114 "token": "some token", 0115 "tokenExpires": { 0116 "$date": 1590844250110 0117 }, 0118 "type": "?????" 0119 } 0120 })"))); // TODO: check the type for non-ldap, non-2fa successful login messages 0121 0122 QCOMPARE(spyStatusChanged.count(), 2); 0123 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoggedIn); 0124 QCOMPARE(authManager.userId(), QStringLiteral("some id")); 0125 QCOMPARE(authManager.authToken(), QStringLiteral("some token")); 0126 } 0127 0128 // Logging in with username and password 0129 { 0130 RocketChatAccount dummyAccount; 0131 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0132 0133 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0134 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0135 authManager.login(QStringLiteral("someuser"), QStringLiteral("somepassword")); 0136 QCOMPARE(spyStatusChanged.count(), 1); 0137 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0138 0139 authManager.processMethodResponse(0, 0140 Utils::strToJsonObject(QStringLiteral( 0141 R"( 0142 { 0143 "msg": "result", 0144 "id": "0", 0145 "result": { 0146 "id": "some id", 0147 "token": "some token", 0148 "tokenExpires": { 0149 "$date": 1590844250110 0150 }, 0151 "type": "ldap" 0152 } 0153 })"))); 0154 0155 QCOMPARE(spyStatusChanged.count(), 2); 0156 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoggedIn); 0157 QCOMPARE(authManager.userId(), QStringLiteral("some id")); 0158 QCOMPARE(authManager.authToken(), QStringLiteral("some token")); 0159 } 0160 0161 // Logging in with OAuth 0162 { 0163 RocketChatAccount dummyAccount; 0164 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0165 0166 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0167 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0168 authManager.loginOAuth(QStringLiteral("sometoken"), QStringLiteral("somesecret")); 0169 QCOMPARE(spyStatusChanged.count(), 1); 0170 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0171 0172 authManager.processMethodResponse(0, 0173 Utils::strToJsonObject(QStringLiteral( 0174 R"( 0175 { 0176 "msg": "result", 0177 "id": "0", 0178 "result": { 0179 "id": "some id", 0180 "token": "some token", 0181 "tokenExpires": { 0182 "$date": 1590844250110 0183 }, 0184 "type": "????" 0185 } 0186 })"))); 0187 0188 QCOMPARE(spyStatusChanged.count(), 2); 0189 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoggedIn); 0190 QCOMPARE(authManager.userId(), QStringLiteral("some id")); 0191 QCOMPARE(authManager.authToken(), QStringLiteral("some token")); 0192 } 0193 } 0194 0195 void DDPAuthenticationManagerTest::testLoginInvalidLoginInfo() 0196 { 0197 RocketChatAccount dummyAccount; 0198 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0199 0200 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0201 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0202 authManager.login(QStringLiteral("wronguser"), QStringLiteral("wrongpassword")); 0203 QCOMPARE(spyStatusChanged.count(), 1); 0204 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0205 0206 authManager.processMethodResponse(0, 0207 Utils::strToJsonObject(QStringLiteral( 0208 R"( 0209 { 0210 "msg": "result", 0211 "id": "0", 0212 "error": { 0213 "isClientSafe": true, 0214 "error": 403, 0215 "reason": "User not found", 0216 "message": "User not found [403]", 0217 "errorType": "Meteor.Error" 0218 } 0219 })"))); 0220 0221 QCOMPARE(spyStatusChanged.count(), 2); 0222 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginFailedInvalidUserOrPassword); 0223 } 0224 0225 void DDPAuthenticationManagerTest::testLoginWithOtpSuccess() 0226 { 0227 RocketChatAccount dummyAccount; 0228 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0229 0230 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0231 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0232 authManager.login(QStringLiteral("wronguser"), QStringLiteral("wrongpassword")); 0233 QCOMPARE(spyStatusChanged.count(), 1); 0234 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0235 0236 authManager.processMethodResponse(0, 0237 Utils::strToJsonObject(QStringLiteral( 0238 R"( 0239 { 0240 "msg": "result", 0241 "id": "0", 0242 "error": { 0243 "isClientSafe": true, 0244 "error": "totp-required", 0245 "reason": "TOTP Required", 0246 "details": { 0247 "method": "email", 0248 "codeGenerated": true, 0249 "availableMethods": [ 0250 "email" 0251 ] 0252 }, 0253 "message": "TOTP Required [totp-required]", 0254 "errorType": "Meteor.Error" 0255 } 0256 })"))); 0257 0258 QCOMPARE(spyStatusChanged.count(), 2); 0259 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOtpRequired); 0260 0261 authManager.sendOTP(QStringLiteral("otpcode")); 0262 QCOMPARE(spyStatusChanged.count(), 3); 0263 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOtpAuthOngoing); 0264 0265 authManager.processMethodResponse(1, 0266 Utils::strToJsonObject(QStringLiteral( 0267 R"( 0268 { 0269 "msg": "result", 0270 "id": "1", 0271 "result": { 0272 "id": "some id", 0273 "token": "some token", 0274 "tokenExpires": { 0275 "$date": 1596139026776 0276 }, 0277 "type": "password" 0278 } 0279 })"))); 0280 0281 QCOMPARE(spyStatusChanged.count(), 4); 0282 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedIn); 0283 QCOMPARE(authManager.userId(), QStringLiteral("some id")); 0284 QCOMPARE(authManager.authToken(), QStringLiteral("some token")); 0285 } 0286 0287 void DDPAuthenticationManagerTest::testLoginWithOtpFailure() 0288 { 0289 RocketChatAccount dummyAccount; 0290 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0291 0292 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0293 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0294 authManager.login(QStringLiteral("wronguser"), QStringLiteral("wrongpassword")); 0295 QCOMPARE(spyStatusChanged.count(), 1); 0296 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0297 0298 authManager.processMethodResponse(0, 0299 Utils::strToJsonObject(QStringLiteral( 0300 R"( 0301 { 0302 "msg": "result", 0303 "id": "0", 0304 "error": { 0305 "isClientSafe": true, 0306 "error": "totp-required", 0307 "reason": "TOTP Required", 0308 "details": { 0309 "method": "email", 0310 "codeGenerated": true, 0311 "availableMethods": [ 0312 "email" 0313 ] 0314 }, 0315 "message": "TOTP Required [totp-required]", 0316 "errorType": "Meteor.Error" 0317 } 0318 })"))); 0319 0320 QCOMPARE(spyStatusChanged.count(), 2); 0321 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOtpRequired); 0322 0323 authManager.sendOTP(QStringLiteral("otpcode")); 0324 QCOMPARE(spyStatusChanged.count(), 3); 0325 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOtpAuthOngoing); 0326 0327 authManager.processMethodResponse(1, 0328 Utils::strToJsonObject(QStringLiteral( 0329 R"( 0330 { 0331 "msg": "result", 0332 "id": "1", 0333 "error": { 0334 "isClientSafe": true, 0335 "error": "totp-invalid", 0336 "reason": "TOTP Invalid", 0337 "details": { 0338 "method": "email" 0339 }, 0340 "message": "TOTP Invalid [totp-invalid]", 0341 "errorType": "Meteor.Error" 0342 } 0343 })"))); 0344 0345 QCOMPARE(spyStatusChanged.count(), 4); 0346 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginFailedInvalidOtp); 0347 } 0348 0349 void DDPAuthenticationManagerTest::testUnknownError() 0350 { 0351 RocketChatAccount dummyAccount; 0352 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0353 0354 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0355 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0356 authManager.login(QStringLiteral("someuser"), QStringLiteral("somepassword")); 0357 QCOMPARE(spyStatusChanged.count(), 1); 0358 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0359 0360 authManager.processMethodResponse(0, Utils::strToJsonObject(QStringLiteral(R"( 0361 { 0362 "msg": "result", 0363 "id": "0", 0364 "error": { 0365 "error": "unknown-error" 0366 } 0367 })"))); 0368 0369 QCOMPARE(spyStatusChanged.count(), 2); 0370 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::GenericError); 0371 } 0372 0373 void DDPAuthenticationManagerTest::testUserNotActivatedError() 0374 { 0375 RocketChatAccount dummyAccount; 0376 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0377 0378 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0379 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0380 authManager.login(QStringLiteral("someuser"), QStringLiteral("somepassword")); 0381 QCOMPARE(spyStatusChanged.count(), 1); 0382 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0383 0384 authManager.processMethodResponse(0, Utils::strToJsonObject(QStringLiteral(R"( 0385 { 0386 "msg": "result", 0387 "id": "0", 0388 "error": { 0389 "error": "error-user-is-not-activated" 0390 } 0391 })"))); 0392 0393 QCOMPARE(spyStatusChanged.count(), 2); 0394 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginFailedUserNotActivated); 0395 } 0396 0397 void DDPAuthenticationManagerTest::testLoginBlockForIpError() 0398 { 0399 RocketChatAccount dummyAccount; 0400 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0401 0402 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0403 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0404 authManager.login(QStringLiteral("someuser"), QStringLiteral("somepassword")); 0405 QCOMPARE(spyStatusChanged.count(), 1); 0406 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0407 0408 authManager.processMethodResponse(0, Utils::strToJsonObject(QStringLiteral(R"( 0409 { 0410 "msg": "result", 0411 "id": "0", 0412 "error": { 0413 "error": "error-login-blocked-for-ip" 0414 } 0415 })"))); 0416 0417 QCOMPARE(spyStatusChanged.count(), 2); 0418 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginFailedLoginBlockForIp); 0419 } 0420 0421 void DDPAuthenticationManagerTest::testLoginBlockedForUser() 0422 { 0423 RocketChatAccount dummyAccount; 0424 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0425 0426 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0427 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0428 authManager.login(QStringLiteral("someuser"), QStringLiteral("somepassword")); 0429 QCOMPARE(spyStatusChanged.count(), 1); 0430 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0431 0432 authManager.processMethodResponse(0, Utils::strToJsonObject(QStringLiteral(R"( 0433 { 0434 "msg": "result", 0435 "id": "0", 0436 "error": { 0437 "error": "error-login-blocked-for-user" 0438 } 0439 })"))); 0440 0441 QCOMPARE(spyStatusChanged.count(), 2); 0442 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginFailedLoginBlockedForUser); 0443 } 0444 0445 void DDPAuthenticationManagerTest::testLoginAppUserAllowToLogin() 0446 { 0447 RocketChatAccount dummyAccount; 0448 DDPAuthenticationManager authManager(dummyAccount.ddp()); 0449 0450 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoggedOut); 0451 QSignalSpy spyStatusChanged(&authManager, &DDPAuthenticationManager::loginStatusChanged); 0452 authManager.login(QStringLiteral("someuser"), QStringLiteral("somepassword")); 0453 QCOMPARE(spyStatusChanged.count(), 1); 0454 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginOngoing); 0455 0456 authManager.processMethodResponse(0, Utils::strToJsonObject(QStringLiteral(R"( 0457 { 0458 "msg": "result", 0459 "id": "0", 0460 "error": { 0461 "error": "error-app-user-is-not-allowed-to-login" 0462 } 0463 })"))); 0464 0465 QCOMPARE(spyStatusChanged.count(), 2); 0466 QCOMPARE(authManager.loginStatus(), DDPAuthenticationManager::LoginStatus::LoginFailedLoginAppNotAllowedToLogin); 0467 } 0468 0469 #include "moc_ddpauthenticationmanagertest.cpp"