~aleteoryx/muditaos

e693cffe4716d0b26b3929913fbd1f235157d7a2 — Pawel Olejniczak 3 years ago cc32dd3
[CP-1232] Extend messages EP API with getThreadByID method

Add API for getting single thread by its ID.
M products/PurePhone/services/desktop/endpoints/include/endpoints/messages/MessageHelper.hpp => products/PurePhone/services/desktop/endpoints/include/endpoints/messages/MessageHelper.hpp +5 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 24,6 24,7 @@ namespace sdesktop::endpoints
        auto deleteDBEntry(Context &context) -> sys::ReturnCodes override;

        static auto toJson(const SMSRecord &record) -> json11::Json;
        static auto toJson(const ThreadRecord &thread) -> json11::Json;
        static auto toJson(const ThreadRecord &thread, const utils::PhoneNumber::View &number) -> json11::Json;
        static auto toJson(const SMSTemplateRecord &record) -> json11::Json;
        static auto fromJson(const json11::Json &msgJson) -> SMSTemplateRecord;


@@ 42,6 43,9 @@ namespace sdesktop::endpoints
        auto updateTemplate(Context &context) -> sys::ReturnCodes;
        auto deleteTemplate(Context &context) -> sys::ReturnCodes;

        void getThreadById(Context &context);
        auto getThreads(Context &context) -> sys::ReturnCodes;

        void requestCount(Context &context);
        void getMessageById(Context &context);
        auto getMessagesByThreadID(Context &context) -> sys::ReturnCodes;


@@ 53,8 57,5 @@ namespace sdesktop::endpoints
        auto getMessagesTemplates(Context &context) -> sys::ReturnCodes;

        json11::Json receivedJson;

        const int defaultLimit = 100; // will be removed after introducing pagination
    };

} // namespace sdesktop::endpoints

M products/PurePhone/services/desktop/endpoints/messages/MessageHelper.cpp => products/PurePhone/services/desktop/endpoints/messages/MessageHelper.cpp +84 -34
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <endpoints/messages/MessageHelper.hpp>


@@ 33,6 33,7 @@
#include <memory>
#include <utility>
#include <module-db/queries/messages/sms/QuerySMSGetByText.hpp>
#include "queries/messages/threads/QueryThreadGetByID.hpp"

namespace sdesktop::endpoints
{


@@ 59,6 60,18 @@ namespace sdesktop::endpoints
        return recordEntry;
    }

    auto MessageHelper::toJson(const ThreadRecord &thread) -> json11::Json
    {

        auto recordEntry = json11::Json::object{{json::messages::lastUpdatedAt, static_cast<int>(thread.date)},
                                                {json::messages::messageCount, static_cast<int>(thread.msgCount)},
                                                {json::messages::threadID, static_cast<int>(thread.ID)},
                                                {json::messages::messageSnippet, thread.snippet.c_str()},
                                                {json::messages::isUnread, thread.isUnread()},
                                                {json::messages::messageType, static_cast<int>(thread.type)}};
        return recordEntry;
    }

    auto MessageHelper::toJson(const ThreadRecord &thread, const utils::PhoneNumber::View &number) -> json11::Json
    {



@@ 351,40 364,11 @@ namespace sdesktop::endpoints

    auto MessageHelper::requestThread(Context &context) -> sys::ReturnCodes
    {
        try {
            auto &ctx                = dynamic_cast<PagedContext &>(context);
            const std::size_t limit  = ctx.getBody()[json::messages::limit].int_value();
            const std::size_t offset = ctx.getBody()[json::messages::offset].int_value();
            ctx.setRequestedLimit(limit);
            ctx.setRequestedOffset(offset);
            auto query = std::make_unique<db::query::ThreadsGetForList>(offset, std::min(ctx.getPageSize(), limit));

            auto listener = std::make_unique<db::EndpointListenerWithPages>(
                [](db::QueryResult *result, PagedContext &context) {
                    if (auto threadsResults = dynamic_cast<db::query::ThreadsGetForListResults *>(result)) {
                        json11::Json::array threadsArray;
                        const auto threads = threadsResults->getResults();
                        const auto numbers = threadsResults->getNumbers();
                        threadsArray.reserve(threads.size());
                        for (std::size_t i = 0; i < threads.size(); ++i) {
                            threadsArray.emplace_back(MessageHelper::toJson(threads[i], numbers[i]));
                        }
                        context.setResponseBody(std::move(threadsArray));
                        context.setTotalCount(threadsResults->getCount());
                        putToSendQueue(context.createSimpleResponse());
                        return true;
                    }
                    else {
                        return false;
                    }
                },
                ctx);
            query->setQueryListener(std::move(listener));
            DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSThread, std::move(query));
        if (context.getBody()[json::messages::threadID].int_value() != 0) {
            getThreadById(context);
        }
        catch (const std::bad_cast &e) {
            LOG_ERROR("exception while requesting thread");
            return sys::ReturnCodes::Failure;
        else {
            return getThreads(context);
        }
        return sys::ReturnCodes::Success;
    }


@@ 439,6 423,72 @@ namespace sdesktop::endpoints
        return sys::ReturnCodes::Success;
    }

    void MessageHelper::getThreadById(Context &context)
    {
        auto query =
            std::make_unique<db::query::ThreadGetByID>(context.getBody()[json::messages::threadID].int_value());

        auto listener = std::make_unique<db::EndpointListener>(
            [](db::QueryResult *result, Context &context) {
                if (auto threadGetByIDResult = dynamic_cast<db::query::ThreadGetByIDResult *>(result)) {
                    auto threadRecord = threadGetByIDResult->getRecord();
                    if (!threadRecord.has_value()) {
                        return false;
                    }
                    context.setResponseBody(MessageHelper::toJson(threadRecord.value()));
                    putToSendQueue(context.createSimpleResponse());
                    return true;
                }
                else {
                    return false;
                }
            },
            context);

        query->setQueryListener(std::move(listener));
        DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSThread, std::move(query));
    }

    auto MessageHelper::getThreads(Context &context) -> sys::ReturnCodes
    {
        try {
            auto &ctx                = dynamic_cast<PagedContext &>(context);
            const std::size_t limit  = ctx.getBody()[json::messages::limit].int_value();
            const std::size_t offset = ctx.getBody()[json::messages::offset].int_value();
            ctx.setRequestedLimit(limit);
            ctx.setRequestedOffset(offset);
            auto query = std::make_unique<db::query::ThreadsGetForList>(offset, std::min(ctx.getPageSize(), limit));

            auto listener = std::make_unique<db::EndpointListenerWithPages>(
                [](db::QueryResult *result, PagedContext &context) {
                    if (auto threadsResults = dynamic_cast<db::query::ThreadsGetForListResults *>(result)) {
                        json11::Json::array threadsArray;
                        const auto threads = threadsResults->getResults();
                        const auto numbers = threadsResults->getNumbers();
                        threadsArray.reserve(threads.size());
                        for (std::size_t i = 0; i < threads.size(); ++i) {
                            threadsArray.emplace_back(MessageHelper::toJson(threads[i], numbers[i]));
                        }
                        context.setResponseBody(std::move(threadsArray));
                        context.setTotalCount(threadsResults->getCount());
                        putToSendQueue(context.createSimpleResponse());
                        return true;
                    }
                    else {
                        return false;
                    }
                },
                ctx);
            query->setQueryListener(std::move(listener));
            DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSThread, std::move(query));
        }
        catch (const std::bad_cast &e) {
            LOG_ERROR("exception while requesting thread");
            return sys::ReturnCodes::Failure;
        }
        return sys::ReturnCodes::Success;
    }

    void MessageHelper::requestCount(Context &context)
    {
        auto query = std::make_unique<db::query::SMSGetCount>();

M test/harness => test/harness +1 -1
@@ 1,1 1,1 @@
Subproject commit 549ac3a09dab95223baa32084ff20afb340be9d5
Subproject commit 577c1191121e5c59f6c7adc81417cd2e95e32c27

M test/pytest/service-desktop/test_message_threads.py => test/pytest/service-desktop/test_message_threads.py +30 -1
@@ 2,7 2,7 @@
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
import pytest
from harness.request import TransactionError
from harness.api.messages import GetThreadsWithOffsetAndLimit, MarkThreadAsUnread, GetMessageById, AddMessage, DeleteMessageById
from harness.api.messages import GetThreadsWithOffsetAndLimit, GetThreadById, MarkThreadAsUnread, GetMessageById, AddMessage, DeleteMessageById


class ThreadsTester:


@@ 17,6 17,14 @@ class ThreadsTester:
        else:
            return True, result

    def get_thread_by_id(self, thread_record_id):
        try:
            result = GetThreadById(thread_record_id).run(self.harness)
        except TransactionError:
            return False
        else:
            return True, result.thread

    def mark_thread_as_unread(self, thread_id, set_thread_unread):
        try:
            result = MarkThreadAsUnread(thread_id, set_thread_unread).run(self.harness)


@@ 109,3 117,24 @@ def test_getting_threads(harness):
        assert type(thread["threadID"]) == int
        message_types = [1, 2, 4, 8, 16, 18, 255]
        assert thread["messageType"] in message_types


@pytest.mark.service_desktop_test
@pytest.mark.usefixtures("phone_unlocked")
def test_get_message_by_id(harness):
    threads_tester = ThreadsTester(harness)

    message_number = "123456789"
    message_body = "Hello, how are you?"

    result, message_record = threads_tester.add_message(message_number, message_body)
    assert result, "Failed to add message!"

    result, received_message_record = threads_tester.get_message_by_id(message_record["messageID"])
    assert result, "Failed to get message by id!"

    result, received_thread_record = threads_tester.get_thread_by_id(received_message_record["threadID"])
    assert result, "Failed to get thread by id!"
    assert received_thread_record["threadID"] == received_message_record["threadID"], "Wrong thread id!"

    assert threads_tester.delete_message_by_id(message_record["messageID"]), "Failed to delete a message!"