M doc/os_api/endpoints/pure/contacts_endpoint.md => doc/os_api/endpoints/pure/contacts_endpoint.md +14 -6
@@ 276,12 276,20 @@ Parameters:
}
```
-Warning:
-In the current implementation, there is no duplicate detection while updating contact.
-Example:
-We have contact A with number 123 and contact B with number 456.
-Contact A is updated with a new number - 456. Number 456 is silently unattached from contact B and assigned to contact
-A. Finally, we have contact A with number 456 and contact B with no number.
+**Response Payload Structure when contact is matched as a duplicate**
+
+```json
+{
+ "body": {
+ "duplicatedNumbers": [
+ "123456789"
+ ]
+ },
+ "endpoint": 7,
+ "status": 409,
+ "uuid": 123
+}
+```
### Delete a contact
M module-db/Interface/ContactRecord.cpp => module-db/Interface/ContactRecord.cpp +19 -6
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "ContactRecord.hpp"
@@ 657,9 657,20 @@ auto ContactRecordInterface::addQuery(const std::shared_ptr<db::Query> &query) -
auto ContactRecordInterface::updateQuery(const std::shared_ptr<db::Query> &query)
-> const std::unique_ptr<db::QueryResult>
{
- auto updateQuery = static_cast<const db::query::ContactUpdate *>(query.get());
- auto result = ContactRecordInterface::Update(updateQuery->rec);
- auto response = std::make_unique<db::query::ContactUpdateResult>(result);
+ auto updateQuery = dynamic_cast<db::query::ContactUpdate *>(query.get());
+ if (updateQuery == nullptr) {
+ LOG_ERROR("Dynamic casting db::query::ContactUpdate has failed!");
+ return std::unique_ptr<db::QueryResult>();
+ }
+ auto result = false;
+
+ // Checking for duplicates along with omitting this contact in the DB in the search
+ auto duplicates = verifyDuplicate(updateQuery->rec, updateQuery->rec.ID);
+ if (duplicates.empty()) {
+ result = ContactRecordInterface::Update(updateQuery->rec);
+ }
+
+ auto response = std::make_unique<db::query::ContactUpdateResult>(result, updateQuery->rec.ID, duplicates);
response->setRequestQuery(query);
response->setRecordID(updateQuery->rec.ID);
return response;
@@ 1540,11 1551,13 @@ auto ContactRecordInterface::CheckContactsListDuplicates(std::vector<ContactReco
return {unique, duplicates};
}
-auto ContactRecordInterface::verifyDuplicate(ContactRecord &record) -> std::vector<utils::PhoneNumber::View>
+auto ContactRecordInterface::verifyDuplicate(ContactRecord &record, const std::uint32_t contactIDToIgnore)
+ -> std::vector<utils::PhoneNumber::View>
{
std::vector<utils::PhoneNumber::View> duplicates = {};
for (const auto &number : record.numbers) {
- auto matchResult = MatchByNumber(number.number);
+ auto matchResult = MatchByNumber(
+ number.number, CreateTempContact::False, utils::PhoneNumber::Match::POSSIBLE, contactIDToIgnore);
if (!matchResult.has_value() || matchResult.value().contact.isTemporary()) {
continue;
}
M module-db/Interface/ContactRecord.hpp => module-db/Interface/ContactRecord.hpp +3 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 250,7 250,8 @@ class ContactRecordInterface : public RecordInterface<ContactRecord, ContactReco
* @param record single contact record to be verified
* @return true if contact can be considered as a duplicate in DB
*/
- auto verifyDuplicate(ContactRecord &record) -> std::vector<utils::PhoneNumber::View>;
+ auto verifyDuplicate(ContactRecord &record, const std::uint32_t contactIDToIgnore = 0u)
+ -> std::vector<utils::PhoneNumber::View>;
/**
* @brief Verify if single contact record can be considered as an existing temporary contact in DB
M module-db/queries/phonebook/QueryContactUpdate.cpp => module-db/queries/phonebook/QueryContactUpdate.cpp +5 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "QueryContactUpdate.hpp"
@@ 11,7 11,10 @@ using namespace db::query;
ContactUpdate::ContactUpdate(const ContactRecord &rec) : Query(Query::Type::Update), rec(std::move(rec))
{}
-ContactUpdateResult::ContactUpdateResult(bool result) : result(result)
+ContactUpdateResult::ContactUpdateResult(bool result,
+ std::uint32_t id,
+ const std::vector<utils::PhoneNumber::View> &duplicates)
+ : result(result), duplicates(duplicates), id(id)
{}
[[nodiscard]] auto ContactUpdate::debugInfo() const -> std::string
M module-db/queries/phonebook/QueryContactUpdate.hpp => module-db/queries/phonebook/QueryContactUpdate.hpp +16 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 24,15 24,29 @@ namespace db::query
class ContactUpdateResult : public QueryResult
{
public:
- ContactUpdateResult(bool result);
+ ContactUpdateResult(bool result, std::uint32_t id, const std::vector<utils::PhoneNumber::View> &duplicates);
auto getResult() -> bool
{
return result;
}
+ [[nodiscard]] auto hasDuplicates() const noexcept -> bool
+ {
+ return !duplicates.empty();
+ }
+ [[nodiscard]] auto getDuplicates() const noexcept -> std::vector<utils::PhoneNumber::View>
+ {
+ return duplicates;
+ }
+ [[nodiscard]] auto getID() const noexcept -> std::uint32_t
+ {
+ return id;
+ }
[[nodiscard]] auto debugInfo() const -> std::string override;
private:
bool result;
+ std::vector<utils::PhoneNumber::View> duplicates;
+ std::uint32_t id;
};
}; // namespace db::query
M products/PurePhone/services/desktop/endpoints/contacts/ContactHelper.cpp => products/PurePhone/services/desktop/endpoints/contacts/ContactHelper.cpp +14 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <endpoints/contacts/ContactHelper.hpp>
@@ 244,9 244,19 @@ namespace sdesktop::endpoints
auto listener = std::make_unique<db::EndpointListener>(
[](db::QueryResult *result, Context context) {
if (auto contactResult = dynamic_cast<db::query::ContactUpdateResult *>(result)) {
-
- context.setResponseStatus(contactResult->getResult() ? http::Code::NoContent
- : http::Code::InternalServerError);
+ if (contactResult->hasDuplicates()) {
+ auto numberDuplicates = json11::Json::array();
+ for (const auto &number : contactResult->getDuplicates()) {
+ numberDuplicates.emplace_back(number.getEntered().c_str());
+ }
+ context.setResponseBody(
+ json11::Json::object({{json::contacts::duplicateNumbers, numberDuplicates}}));
+ context.setResponseStatus(http::Code::Conflict);
+ }
+ else {
+ context.setResponseStatus(contactResult->getResult() ? http::Code::NoContent
+ : http::Code::InternalServerError);
+ }
putToSendQueue(context.createSimpleResponse());
return true;
M pure_changelog.md => pure_changelog.md +11 -2
@@ 2,14 2,23 @@
## Unreleased
+### Fixed
+Fixed no response when editing a contact via Center to have the same number as another
+
+### Added
+
+### Changed / Improved
+
+
+## [1.11.0 2023-12-15]
+
### Added
* Added VoLTE support in Denmark, United Kingdom, Netherlands, Canada and Austria
### Changed / Improved
-* Hide the SOS label during onboarding when the modem is not ready for an emergency call.
-* Anonymization sensitive data in logs added.
+* Added anonymization of sensitive data in logs.
### Fixed