File indexing completed on 2024-05-05 17:00:21
0001 /* 0002 SPDX-FileCopyrightText: 2018-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "restapiabstractjob.h" 0008 #include "abstractlogger.h" 0009 #include "rocketchatqtrestapi_debug.h" 0010 #include <KLocalizedString> 0011 #include <QJsonDocument> 0012 #include <QJsonObject> 0013 #include <QUrlQuery> 0014 0015 using namespace RocketChatRestApi; 0016 RestApiAbstractJob::RestApiAbstractJob(QObject *parent) 0017 : QObject(parent) 0018 { 0019 } 0020 0021 RestApiAbstractJob::~RestApiAbstractJob() 0022 { 0023 if (mReply) { 0024 mReply->disconnect(this); 0025 } 0026 } 0027 0028 QNetworkAccessManager *RestApiAbstractJob::networkAccessManager() const 0029 { 0030 return mNetworkAccessManager; 0031 } 0032 0033 void RestApiAbstractJob::setNetworkAccessManager(QNetworkAccessManager *networkAccessManager) 0034 { 0035 mNetworkAccessManager = networkAccessManager; 0036 } 0037 0038 RocketChatRestApi::RestApiMethod *RestApiAbstractJob::restApiMethod() const 0039 { 0040 return mRestApiMethod; 0041 } 0042 0043 void RestApiAbstractJob::setRestApiMethod(RocketChatRestApi::RestApiMethod *restApiMethod) 0044 { 0045 mRestApiMethod = restApiMethod; 0046 } 0047 0048 QString RestApiAbstractJob::authToken() const 0049 { 0050 return mAuthToken; 0051 } 0052 0053 void RestApiAbstractJob::setAuthToken(const QString &authToken) 0054 { 0055 mAuthToken = authToken; 0056 } 0057 0058 QString RestApiAbstractJob::userId() const 0059 { 0060 return mUserId; 0061 } 0062 0063 void RestApiAbstractJob::setUserId(const QString &userId) 0064 { 0065 mUserId = userId; 0066 } 0067 0068 bool RestApiAbstractJob::hasAuthenticationValue() const 0069 { 0070 return !mAuthToken.isEmpty() && !mUserId.isEmpty(); 0071 } 0072 0073 bool RestApiAbstractJob::requireTwoFactorAuthentication() const 0074 { 0075 return false; 0076 } 0077 0078 bool RestApiAbstractJob::hasQueryParameterSupport() const 0079 { 0080 return false; 0081 } 0082 0083 bool RestApiAbstractJob::enforcePasswordFallback() const 0084 { 0085 return mEnforcePasswordFallBack; 0086 } 0087 0088 void RestApiAbstractJob::setEnforcePasswordFallback(bool enforce) 0089 { 0090 mEnforcePasswordFallBack = enforce; 0091 } 0092 0093 bool RestApiAbstractJob::canStart() const 0094 { 0095 if (requireTwoFactorAuthentication() && mEnforcePasswordFallBack) { 0096 if (mAuthMethod.isEmpty() || mAuthCode.isEmpty()) { 0097 qCWarning(ROCKETCHATQTRESTAPI_LOG) << "Job required two factor auth but mAuthMethod or mAuthCode is empty"; 0098 return false; 0099 } 0100 } 0101 if (!mNetworkAccessManager) { 0102 qCWarning(ROCKETCHATQTRESTAPI_LOG) << "Network manager not defined"; 0103 return false; 0104 } 0105 if (!mRestApiMethod) { 0106 qCWarning(ROCKETCHATQTRESTAPI_LOG) << "RestApiMethod not defined"; 0107 return false; 0108 } 0109 if (requireHttpAuthentication() && !hasAuthenticationValue()) { 0110 qCWarning(ROCKETCHATQTRESTAPI_LOG) << "Auth settings is empty. It's a bug"; 0111 return false; 0112 } 0113 return true; 0114 } 0115 0116 void RestApiAbstractJob::addRequestAttribute(QNetworkRequest &request, bool addContentTypeHeader) const 0117 { 0118 request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); 0119 request.setAttribute(QNetworkRequest::Http2AllowedAttribute, true); 0120 if (addContentTypeHeader) { 0121 request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/json")); 0122 } 0123 } 0124 0125 void RestApiAbstractJob::addAuthRawHeader(QNetworkRequest &request) const 0126 { 0127 request.setRawHeader(QByteArrayLiteral("X-Auth-Token"), mAuthToken.toLocal8Bit()); 0128 request.setRawHeader(QByteArrayLiteral("X-User-Id"), mUserId.toLocal8Bit()); 0129 if (requireTwoFactorAuthentication() && mEnforcePasswordFallBack) { 0130 if (!mAuthMethod.isEmpty() && !mAuthCode.isEmpty()) { 0131 request.setRawHeader(QByteArrayLiteral("x-2fa-code"), mAuthCode.toLocal8Bit()); 0132 request.setRawHeader(QByteArrayLiteral("x-2fa-method"), mAuthMethod.toLocal8Bit()); 0133 } 0134 } 0135 } 0136 0137 QueryParameters RestApiAbstractJob::queryParameters() const 0138 { 0139 return mQueryParameters; 0140 } 0141 0142 void RestApiAbstractJob::setQueryParameters(const QueryParameters &queryParameters) 0143 { 0144 mQueryParameters = queryParameters; 0145 } 0146 0147 void RestApiAbstractJob::addQueryParameter(QUrlQuery &urlQuery) const 0148 { 0149 if (hasQueryParameterSupport() && mQueryParameters.isValid()) { 0150 QueryParameters::generateQueryParameter(mQueryParameters, urlQuery); 0151 } 0152 // qDebug() << " urlQuery " << urlQuery.toString(); 0153 } 0154 0155 RocketChatRestApi::AbstractLogger *RestApiAbstractJob::restApiLogger() const 0156 { 0157 return mRestApiLogger; 0158 } 0159 0160 void RestApiAbstractJob::setRestApiLogger(RocketChatRestApi::AbstractLogger *ruqolaLogger) 0161 { 0162 mRestApiLogger = ruqolaLogger; 0163 } 0164 0165 void RestApiAbstractJob::addLoggerInfo(const QByteArray &str) 0166 { 0167 if (mRestApiLogger) { // when $RUQOLA_LOGFILE is set 0168 mRestApiLogger->dataSent("RESTAPI: " + str); 0169 } else { 0170 qCDebug(ROCKETCHATQTRESTAPI_LOG) << "RESTAPI: " << str; 0171 } 0172 } 0173 0174 void RestApiAbstractJob::addStartRestApiInfo(const QByteArray &str) 0175 { 0176 if (mRestApiLogger) { // when $RUQOLA_LOGFILE is set 0177 mRestApiLogger->dataSent(AbstractLogger::RESTApiType, "RESTAPI:", str); 0178 } else { 0179 qCDebug(ROCKETCHATQTRESTAPI_LOG) << "RESTAPI: " << str; 0180 } 0181 } 0182 0183 void RestApiAbstractJob::addLoggerWarning(const QByteArray &str) 0184 { 0185 if (mRestApiLogger) { 0186 mRestApiLogger->dataSent(AbstractLogger::RESTApiType, "WARNING RESTAPI: ", str); 0187 } else { 0188 qCWarning(ROCKETCHATQTRESTAPI_LOG) << "RESTAPI: " << str; 0189 } 0190 } 0191 0192 void RestApiAbstractJob::emitFailedMessage(const QString &replyErrorString, const QJsonObject &replyObject) 0193 { 0194 Q_EMIT failed(replyErrorString + QLatin1Char('\n') + errorStr(replyObject)); 0195 } 0196 0197 QString RestApiAbstractJob::errorStr(const QJsonObject &replyObject) 0198 { 0199 // JSon-level error 0200 const QString errorType = replyObject[QLatin1String("errorType")].toString(); 0201 if (!errorType.isEmpty()) { 0202 qCWarning(ROCKETCHATQTRESTAPI_LOG) << "errorType" << errorType; 0203 const QString trStr = errorMessage(errorType, replyObject[QLatin1String("details")].toObject()); 0204 if (!trStr.isEmpty()) { 0205 return trStr; 0206 } else { 0207 qCWarning(ROCKETCHATQTRESTAPI_LOG) << " errorType not defined as translated message: " << errorType; 0208 return i18n("Unauthorized"); 0209 } 0210 } else if (replyObject[QLatin1String("status")].toString() == QLatin1String("error")) { 0211 const QString message = replyObject[QLatin1String("message")].toString(); 0212 qCWarning(ROCKETCHATQTRESTAPI_LOG) << "message error " << message; 0213 return generateErrorMessage(message); 0214 } else { 0215 const QString error = replyObject[QLatin1String("error")].toString(); 0216 qCWarning(ROCKETCHATQTRESTAPI_LOG) << "error " << error; 0217 return generateErrorMessage(error); 0218 } 0219 } 0220 0221 QString RestApiAbstractJob::generateErrorMessage(const QString &errorStr) const 0222 { 0223 if (jobName().isEmpty()) { 0224 return errorStr; 0225 } 0226 return i18n("%1:%2", jobName(), errorStr); 0227 } 0228 0229 QString RestApiAbstractJob::errorMessage(const QString &str, const QJsonObject &details) 0230 { 0231 qDebug() << " details " << details; 0232 if (str == QLatin1String("error-action-not-allowed")) { 0233 const QString actionName = details[QLatin1String("action")].toString(); 0234 return i18n("'%1' is not allowed", actionName); 0235 } else if (str == QLatin1String("error-application-not-found")) { 0236 return i18n("Application not found"); 0237 } else if (str == QLatin1String("error-archived-duplicate-name")) { 0238 const QString roomName = details[QLatin1String("room_name")].toString(); 0239 return i18n("There's an archived channel with name '%1'", roomName); 0240 } else if (str == QLatin1String("error-cant-invite-for-direct-room")) { 0241 return i18n("Can't invite user to direct rooms"); 0242 } else if (str == QLatin1String("error-channels-setdefault-is-same")) { 0243 return i18n("The channel default setting is the same as what it would be changed to."); 0244 } else if (str == QLatin1String("error-channels-setdefault-missing-default-param")) { 0245 return i18n("The bodyParam 'default' is required"); 0246 } else if (str == QLatin1String("error-could-not-change-email")) { 0247 return i18n("Could not change email"); 0248 } else if (str == QLatin1String("error-could-not-change-name")) { 0249 return i18n("Could not change name"); 0250 } else if (str == QLatin1String("error-could-not-change-username")) { 0251 return i18n("Could not change username"); 0252 } else if (str == QLatin1String("error-delete-protected-role")) { 0253 return i18n("Cannot delete a protected role"); 0254 } else if (str == QLatin1String("error-department-not-found")) { 0255 return i18n("Department not found"); 0256 } else if (str == QLatin1String("error-direct-message-file-upload-not-allowed")) { 0257 return i18n("File sharing not allowed in direct messages"); 0258 } else if (str == QLatin1String("error-duplicate-channel-name")) { 0259 const QString channelName = details[QLatin1String("channel_name")].toString(); 0260 return i18n("A channel with name '%1' exists", channelName); 0261 } else if (str == QLatin1String("error-edit-permissions-not-allowed")) { 0262 return i18n("Editing permissions is not allowed"); 0263 } else if (str == QLatin1String("error-email-domain-blacklisted")) { 0264 return i18n("The email domain is blacklisted"); 0265 } else if (str == QLatin1String("error-email-send-failed")) { 0266 const QString message = details[QLatin1String("message")].toString(); 0267 return i18n("Error trying to send email: %1", message); 0268 } else if (str == QLatin1String("error-field-unavailable")) { 0269 const QString field = details[QLatin1String("field")].toString(); 0270 return i18n("'%1' is already in use :(", field); 0271 } else if (str == QLatin1String("error-file-too-large")) { 0272 return i18n("File is too large"); 0273 } else if (str == QLatin1String("error-importer-not-defined")) { 0274 return i18n("The importer was not defined correctly, it is missing the Import class."); 0275 } else if (str == QLatin1String("error-import-file-extract-error")) { 0276 return i18n("Failed to extract import file."); 0277 } else if (str == QLatin1String("error-import-file-is-empty")) { 0278 return i18n("Imported file seems to be empty."); 0279 } else if (str == QLatin1String("error-import-file-missing")) { 0280 return i18n("The file to be imported was not found on the specified path."); 0281 } else if (str == QLatin1String("error-input-is-not-a-valid-field")) { 0282 const QString field = details[QLatin1String("field")].toString(); 0283 const QString input = details[QLatin1String("input")].toString(); 0284 return i18n("%1 is not a valid %2", input, field); 0285 } else if (str == QLatin1String("error-invalid-actionlink")) { 0286 return i18n("Invalid action link"); 0287 } else if (str == QLatin1String("error-invalid-account")) { 0288 return i18n("Invalid Account"); 0289 } else if (str == QLatin1String("error-invalid-arguments")) { 0290 return i18n("Invalid arguments"); 0291 } else if (str == QLatin1String("error-invalid-asset")) { 0292 return i18n("Invalid asset"); 0293 } else if (str == QLatin1String("error-invalid-channel")) { 0294 return i18n("Invalid channel."); 0295 } else if (str == QLatin1String("error-invalid-channel-start-with-chars")) { 0296 return i18n("Invalid channel. Start with @ or #"); 0297 } else if (str == QLatin1String("error-invalid-custom-field")) { 0298 return i18n("Invalid custom field"); 0299 } else if (str == QLatin1String("error-invalid-custom-field-name")) { 0300 return i18n("Invalid custom field name. Use only letters, numbers, hyphens and underscores."); 0301 } else if (str == QLatin1String("error-invalid-date")) { 0302 return i18n("Invalid date provided."); 0303 } else if (str == QLatin1String("error-invalid-description")) { 0304 return i18n("Invalid description"); 0305 } else if (str == QLatin1String("error-invalid-domain")) { 0306 return i18n("Invalid domain"); 0307 } else if (str == QLatin1String("error-invalid-email")) { 0308 const QString email = details[QLatin1String("email")].toString(); 0309 return i18n("Invalid email '%1'", email); 0310 } else if (str == QLatin1String("error-invalid-email-address")) { 0311 return i18n("Invalid email address"); 0312 } else if (str == QLatin1String("error-invalid-file-height")) { 0313 return i18n("Invalid file height"); 0314 } else if (str == QLatin1String("error-invalid-file-type")) { 0315 return i18n("Invalid file type"); 0316 } else if (str == QLatin1String("error-invalid-file-width")) { 0317 return i18n("Invalid file width"); 0318 } else if (str == QLatin1String("error-invalid-from-address")) { 0319 return i18n("You informed an invalid FROM address."); 0320 } else if (str == QLatin1String("error-invalid-integration")) { 0321 return i18n("Invalid integration"); 0322 } else if (str == QLatin1String("error-invalid-message")) { 0323 return i18n("Invalid message"); 0324 } else if (str == QLatin1String("error-invalid-method")) { 0325 return i18n("Invalid method"); 0326 } else if (str == QLatin1String("error-invalid-name")) { 0327 return i18n("Invalid name"); 0328 } else if (str == QLatin1String("error-invalid-password")) { 0329 return i18n("Invalid password"); 0330 } else if (str == QLatin1String("error-invalid-permission")) { 0331 return i18n("Invalid permission"); 0332 } else if (str == QLatin1String("error-invalid-redirectUri")) { 0333 return i18n("Invalid redirectUri"); 0334 } else if (str == QLatin1String("error-invalid-role")) { 0335 return i18n("Invalid role"); 0336 } else if (str == QLatin1String("error-invalid-room")) { 0337 return i18n("Invalid room"); 0338 } else if (str == QLatin1String("error-invalid-room-name")) { 0339 const QString roomName = details[QLatin1String("room_name")].toString(); 0340 return i18n("'%1' is not a valid room name", roomName); 0341 } else if (str == QLatin1String("error-invalid-room-type")) { 0342 const QString roomType = details[QLatin1String("type")].toString(); 0343 return i18n("'%1' is not a valid room type.", roomType); 0344 } else if (str == QLatin1String("error-invalid-settings")) { 0345 return i18n("Invalid settings provided"); 0346 } else if (str == QLatin1String("error-invalid-subscription")) { 0347 return i18n("Invalid subscription"); 0348 } else if (str == QLatin1String("error-invalid-token")) { 0349 return i18n("Invalid token"); 0350 } else if (str == QLatin1String("error-invalid-triggerWords")) { 0351 return i18n("Invalid triggerWords"); 0352 } else if (str == QLatin1String("error-invalid-urls")) { 0353 return i18n("Invalid URLs"); 0354 } else if (str == QLatin1String("error-invalid-user")) { 0355 return i18n("Invalid user"); 0356 } else if (str == QLatin1String("error-invalid-username")) { 0357 return i18n("Invalid username"); 0358 } else if (str == QLatin1String("error-invalid-webhook-response")) { 0359 return i18n("The webhook URL responded with a status other than 200"); 0360 } else if (str == QLatin1String("error-message-deleting-blocked")) { 0361 return i18n("Message deleting is blocked"); 0362 } else if (str == QLatin1String("error-message-editing-blocked")) { 0363 return i18n("Message editing is blocked"); 0364 } else if (str == QLatin1String("error-message-size-exceeded")) { 0365 return i18n("Message size exceeds Message_MaxAllowedSize"); 0366 } else if (str == QLatin1String("error-missing-unsubscribe-link")) { 0367 return i18n("You must provide the [unsubscribe] link."); 0368 } else if (str == QLatin1String("error-no-tokens-for-this-user")) { 0369 return i18n("There are no tokens for this user"); 0370 } else if (str == QLatin1String("error-not-allowed")) { 0371 return i18n("Not allowed"); 0372 } else if (str == QLatin1String("error-not-authorized")) { 0373 return i18n("Not authorized"); 0374 } else if (str == QLatin1String("not-authorized")) { 0375 return i18n("Not authorized"); 0376 } else if (str == QLatin1String("error-password-policy-not-met")) { 0377 return i18n("Password does not meet the server's policy"); 0378 } else if (str == QLatin1String("error-password-policy-not-met-maxLength")) { 0379 return i18n("Password does not meet the server's policy of maximum length (password too long)"); 0380 } else if (str == QLatin1String("error-password-policy-not-met-minLength")) { 0381 return i18n("Password does not meet the server's policy of minimum length (password too short)"); 0382 } else if (str == QLatin1String("error-password-policy-not-met-oneLowercase")) { 0383 return i18n("Password does not meet the server's policy of at least one lowercase character"); 0384 } else if (str == QLatin1String("error-password-policy-not-met-oneNumber")) { 0385 return i18n("Password does not meet the server's policy of at least one numerical character"); 0386 } else if (str == QLatin1String("error-password-policy-not-met-oneSpecial")) { 0387 return i18n("Password does not meet the server's policy of at least one special character"); 0388 } else if (str == QLatin1String("error-password-policy-not-met-oneUppercase")) { 0389 return i18n("Password does not meet the server's policy of at least one uppercase character"); 0390 } else if (str == QLatin1String("error-password-policy-not-met-repeatingCharacters")) { 0391 return i18n( 0392 "Password does not meet the server's policy of forbidden repeating characters (you have too many of the same characters next to each other)"); 0393 } else if (str == QLatin1String("error-push-disabled")) { 0394 return i18n("Push is disabled"); 0395 } else if (str == QLatin1String("error-remove-last-owner")) { 0396 return i18n("This is the last owner. Please set a new owner before removing this one."); 0397 } else if (str == QLatin1String("error-role-in-use")) { 0398 return i18n("Cannot delete role because it's in use"); 0399 } else if (str == QLatin1String("error-role-name-required")) { 0400 return i18n("Role name is required"); 0401 } else if (str == QLatin1String("error-room-is-not-closed")) { 0402 return i18n("Room is not closed"); 0403 } else if (str == QLatin1String("error-the-field-is-required")) { 0404 const QString field = details[QLatin1String("field")].toString(); 0405 return i18n("The field '%1' is required.", field); 0406 } else if (str == QLatin1String("error-this-is-not-a-livechat-room")) { 0407 return i18n("This is not a Livechat room"); 0408 } else if (str == QLatin1String("error-personal-access-tokens-are-current-disabled")) { 0409 return i18n("Personal Access Tokens are currently disabled"); 0410 } else if (str == QLatin1String("error-token-already-exists")) { 0411 return i18n("A token with this name already exists"); 0412 } else if (str == QLatin1String("error-token-does-not-exists")) { 0413 return i18n("Token does not exists"); 0414 } else if (str == QLatin1String("error-too-many-requests")) { 0415 const QString seconds = details[QLatin1String("seconds")].toString(); 0416 return i18n("Error, too many requests. Please slow down. You must wait %1 seconds before trying again.", seconds); 0417 } else if (str == QLatin1String("error-user-has-no-roles")) { 0418 return i18n("User has no roles"); 0419 } else if (str == QLatin1String("error-user-is-not-activated")) { 0420 return i18n("User is not activated"); 0421 } else if (str == QLatin1String("error-user-limit-exceeded")) { 0422 return i18n("The number of users you are trying to invite to #channel_name exceeds the limit set by the administrator"); 0423 } else if (str == QLatin1String("error-user-not-in-room")) { 0424 return i18n("User is not in this room"); 0425 } else if (str == QLatin1String("error-logged-user-not-in-room")) { 0426 return i18n("You are not in the room `%s`"); 0427 } else if (str == QLatin1String("error-user-registration-disabled")) { 0428 return i18n("User registration is disabled"); 0429 } else if (str == QLatin1String("error-user-registration-secret")) { 0430 return i18n("User registration is only allowed via Secret URL"); 0431 } else if (str == QLatin1String("error-you-are-last-owner")) { 0432 return i18n("You are the last owner. Please set new owner before leaving the room."); 0433 } else if (str == QLatin1String("error-room-archived")) { 0434 return i18n("The private group is archived"); 0435 } else if (str == QLatin1String("error-user-already-owner")) { 0436 return i18n("User is already an owner"); 0437 } else if (str == QLatin1String("error-user-already-leader")) { 0438 return i18n("User is already a leader"); 0439 } else if (str == QLatin1String("error-user-already-moderator")) { 0440 return i18n("User is already a moderator"); 0441 } else if (str == QLatin1String("error-invalid-message_id")) { 0442 return i18n("Invalid message id"); 0443 } else if (str == QLatin1String("error-user-not-leader")) { 0444 return i18n("User is not a leader"); 0445 } else if (str == QLatin1String("error-app-user-is-not-allowed-to-login")) { 0446 return i18n("App user is not allowed to login"); 0447 } else if (str == QLatin1String("error-direct-message-room")) { 0448 return i18n("Direct Messages can not be archived"); 0449 } else if (str == QLatin1String("error-message-not-found")) { 0450 return i18n("Message not found."); 0451 } else if (str == QLatin1String("totp-required")) { 0452 return i18n("Two Authentication Password Required"); 0453 } else if (str == QLatin1String("totp-invalid")) { 0454 return i18n("Invalid Password"); 0455 } else if (str == QLatin1String("error-room-not-found")) { 0456 return i18n("The required \\\"roomId\\\" or \\\"roomName\\\" param provided does not match any channel"); 0457 } else if (str == QLatin1String("error-role-already-present")) { 0458 return i18n("A role with this name already exists"); 0459 } else if (str == QLatin1String("error-pinning-message")) { 0460 return i18n("Message could not be pinned"); 0461 } else if (str == QLatin1String("error-password-in-history")) { 0462 return i18n("Entered password has been previously used"); 0463 } else if (str == QLatin1String("error-max-rooms-per-guest-reached")) { 0464 return i18n("The maximum number of rooms per guest has been reached."); 0465 } else { 0466 qCWarning(ROCKETCHATQTRESTAPI_LOG) << " unknown error type " << str; 0467 return {}; 0468 } 0469 } 0470 0471 QString RestApiAbstractJob::jobName() const 0472 { 0473 return {}; 0474 } 0475 0476 void RestApiAbstractJob::genericResponseHandler(void (RestApiAbstractJob::*responseHandler)(const QString &, const QJsonDocument &)) 0477 { 0478 if (!mReply) { 0479 deleteLater(); 0480 return; 0481 } 0482 0483 if (mReply->error() != QNetworkReply::NoError) { 0484 if (mReply->error() == QNetworkReply::NetworkSessionFailedError) { 0485 // Ignore NetworkSessionFailedError. It will be handled in Connection class. 0486 // no deleting, we will be trying to destroy everything and relogin 0487 // reply will be invalid at this point, deleting it will crash us 0488 qCWarning(ROCKETCHATQTRESTAPI_LOG) << "NetworkSessionFailedError. Lost connection? "; 0489 return; 0490 } 0491 // TODO add support error 400 0492 (this->*responseHandler)(mReply->errorString(), convertToJsonDocument(mReply)); 0493 } else { 0494 (this->*responseHandler)(QString(), convertToJsonDocument(mReply)); 0495 } 0496 0497 mReply->deleteLater(); 0498 deleteLater(); 0499 } 0500 0501 QDateTime RestApiAbstractJob::updatedSince() const 0502 { 0503 return mUpdatedSince; 0504 } 0505 0506 void RestApiAbstractJob::setUpdatedSince(const QDateTime &newUpdatedSince) 0507 { 0508 mUpdatedSince = newUpdatedSince; 0509 } 0510 0511 const QString &RestApiAbstractJob::authCode() const 0512 { 0513 return mAuthCode; 0514 } 0515 0516 void RestApiAbstractJob::setAuthCode(const QString &newAuthCode) 0517 { 0518 mAuthCode = newAuthCode; 0519 } 0520 0521 const QString &RestApiAbstractJob::authMethod() const 0522 { 0523 return mAuthMethod; 0524 } 0525 0526 void RestApiAbstractJob::setAuthMethod(const QString &newAuthMethod) 0527 { 0528 mAuthMethod = newAuthMethod; 0529 } 0530 0531 void RestApiAbstractJob::submitDeleteRequest() 0532 { 0533 mReply = mNetworkAccessManager->deleteResource(request()); 0534 const QByteArray className = metaObject()->className(); 0535 mReply->setProperty("jobClassName", className); 0536 0537 connect(mReply.data(), &QNetworkReply::finished, this, [this] { 0538 genericResponseHandler(&RestApiAbstractJob::onDeleteRequestResponse); 0539 }); 0540 } 0541 0542 void RestApiAbstractJob::submitGetRequest() 0543 { 0544 mReply = mNetworkAccessManager->get(request()); 0545 const QByteArray className = metaObject()->className(); 0546 mReply->setProperty("jobClassName", className); 0547 0548 connect(mReply.data(), &QNetworkReply::finished, this, [this] { 0549 genericResponseHandler(&RestApiAbstractJob::onGetRequestResponse); 0550 }); 0551 } 0552 0553 void RestApiAbstractJob::submitPostRequest(const QJsonDocument &doc) 0554 { 0555 const QByteArray baPostData = doc.isNull() ? QByteArray() : doc.toJson(QJsonDocument::Compact); 0556 mReply = mNetworkAccessManager->post(request(), baPostData); 0557 const QByteArray className = metaObject()->className(); 0558 mReply->setProperty("jobClassName", className); 0559 0560 addLoggerInfo(className + " started " + baPostData); 0561 0562 connect(mReply.data(), &QNetworkReply::finished, this, [this] { 0563 genericResponseHandler(&RestApiAbstractJob::onPostRequestResponse); 0564 }); 0565 } 0566 0567 QJsonDocument RestApiAbstractJob::convertToJsonDocument(QNetworkReply *reply) 0568 { 0569 const QByteArray data = reply->readAll(); 0570 const QJsonDocument replyDocument = QJsonDocument::fromJson(data); 0571 if (replyDocument.isNull()) { 0572 qCWarning(ROCKETCHATQTRESTAPI_LOG) << " convertToJsonObject return null jsondocument. It's a bug "; 0573 } 0574 return replyDocument; 0575 } 0576 0577 QueryParameters::QueryParameters() = default; 0578 0579 QString QueryParameters::filter() const 0580 { 0581 return mFilter; 0582 } 0583 0584 void QueryParameters::setFilter(const QString &filter) 0585 { 0586 mFilter = filter; 0587 } 0588 0589 int QueryParameters::offset() const 0590 { 0591 return mOffset; 0592 } 0593 0594 void QueryParameters::setOffset(int offset) 0595 { 0596 mOffset = offset; 0597 } 0598 0599 int QueryParameters::count() const 0600 { 0601 return mCount; 0602 } 0603 0604 void QueryParameters::setCount(int count) 0605 { 0606 mCount = count; 0607 } 0608 0609 bool QueryParameters::isValid() const 0610 { 0611 return (mCount >= 0) || (mOffset >= 0) || (!mSorting.isEmpty()) || !mCustom.isEmpty() || !mSearchString.isEmpty() || !mFilter.isEmpty(); 0612 } 0613 0614 QMap<QString, QueryParameters::SortOrder> QueryParameters::sorting() const 0615 { 0616 return mSorting; 0617 } 0618 0619 void QueryParameters::setSorting(const QMap<QString, QueryParameters::SortOrder> &sorting) 0620 { 0621 mSorting = sorting; 0622 } 0623 0624 QString QueryParameters::type() const 0625 { 0626 return mType; 0627 } 0628 0629 void QueryParameters::setType(const QString &type) 0630 { 0631 mType = type; 0632 } 0633 0634 QMap<QString, QString> QueryParameters::custom() const 0635 { 0636 return mCustom; 0637 } 0638 0639 void QueryParameters::setCustom(const QMap<QString, QString> &custom) 0640 { 0641 mCustom = custom; 0642 } 0643 0644 void QueryParameters::generateQueryParameter(const QueryParameters &queryParameters, QUrlQuery &urlQuery) 0645 { 0646 if (queryParameters.count() >= 0) { 0647 urlQuery.addQueryItem(QStringLiteral("count"), QString::number(queryParameters.count())); 0648 } 0649 if (queryParameters.offset() >= 0) { 0650 urlQuery.addQueryItem(QStringLiteral("offset"), QString::number(queryParameters.offset())); 0651 } 0652 if (!queryParameters.filter().isEmpty()) { 0653 urlQuery.addQueryItem(QStringLiteral("filter"), queryParameters.filter()); 0654 } 0655 0656 const QMap<QString, QString> custom = queryParameters.custom(); 0657 if (!custom.isEmpty()) { 0658 QMapIterator<QString, QString> i(custom); 0659 QString str; 0660 while (i.hasNext()) { 0661 i.next(); 0662 if (!str.isEmpty()) { 0663 str += QLatin1Char(','); 0664 } 0665 str += QLatin1Char('"') + i.key() + QLatin1Char('"') + QLatin1Char(':'); 0666 str += QLatin1Char('"') + i.value() + QLatin1Char('"'); 0667 } 0668 str = QStringLiteral("{%1}").arg(str); 0669 0670 urlQuery.addQueryItem(QStringLiteral("query"), str); 0671 } 0672 if (!queryParameters.searchString().isEmpty()) { 0673 const QString str = QStringLiteral(R"({"name":{"$regex":"%1","$options":"i"}})").arg(queryParameters.searchString()); 0674 urlQuery.addQueryItem(QStringLiteral("query"), str); 0675 } 0676 0677 if (!queryParameters.sorting().isEmpty()) { 0678 // example sort={"name" : -1,"status" : 1} 0679 QMapIterator<QString, QueryParameters::SortOrder> i(queryParameters.sorting()); 0680 QString str; 0681 while (i.hasNext()) { 0682 i.next(); 0683 if (!str.isEmpty()) { 0684 str += QLatin1Char(','); 0685 } 0686 str += QLatin1Char('"') + i.key() + QLatin1Char('"') + QLatin1Char(':'); 0687 switch (i.value()) { 0688 case QueryParameters::SortOrder::Ascendant: 0689 str += QString::number(1); 0690 break; 0691 case QueryParameters::SortOrder::Descendant: 0692 str += QString::number(-1); 0693 break; 0694 case QueryParameters::SortOrder::NoSorting: 0695 qCWarning(ROCKETCHATQTRESTAPI_LOG) << "It's not a sorting attribute"; 0696 break; 0697 } 0698 } 0699 str = QStringLiteral("{%1}").arg(str); 0700 0701 // It's ok for getAllMentions.... 0702 urlQuery.addQueryItem(QStringLiteral("sort"), str); 0703 } 0704 if (!queryParameters.type().isEmpty()) { 0705 urlQuery.addQueryItem(QStringLiteral("type"), queryParameters.type()); 0706 } 0707 } 0708 0709 const QString &QueryParameters::searchString() const 0710 { 0711 return mSearchString; 0712 } 0713 0714 void QueryParameters::setSearchString(const QString &newSearchString) 0715 { 0716 mSearchString = newSearchString; 0717 } 0718 0719 #include "moc_restapiabstractjob.cpp"