~aleteoryx/muditaos

25a5d90f4e12ee5d33f4202170f18b59e16a9564 — rrandomsky 2 years ago abe676e pure_1.12.0-rc.1
[CP-2156] Fixed no response when editing a contact to have the same number as another

Fixed no response on Center side when editing a contact to have
the same number as another contact in phonebook.
Added a duplicate number to the response body.
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