Add general API to set per user settings using adhoc commands which can be defaulted from config file. Add 'Send messages as headlines' Transport setting
This commit is contained in:
parent
ad8ed5be56
commit
0b0e020cdf
13 changed files with 196 additions and 8 deletions
|
@ -44,6 +44,13 @@ class AdHocCommandFactory {
|
|||
virtual std::string getNode() = 0;
|
||||
|
||||
virtual std::string getName() = 0;
|
||||
|
||||
virtual std::map<std::string, std::string> &getUserSettings() {
|
||||
return m_userSettings;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::map<std::string, std::string> m_userSettings;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@ class AdHocManager : public Swift::Responder<Swift::Command> {
|
|||
private:
|
||||
virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::Command> payload);
|
||||
virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::Command> payload);
|
||||
|
||||
void handleUserCreated(User *user);
|
||||
|
||||
Component *m_component;
|
||||
DiscoItemsResponder *m_discoItemsResponder;
|
||||
|
|
|
@ -70,6 +70,7 @@ message ConversationMessage {
|
|||
optional string nickname = 4;
|
||||
optional string xhtml = 5;
|
||||
optional string timestamp = 6;
|
||||
optional bool headline = 7;
|
||||
}
|
||||
|
||||
message Room {
|
||||
|
|
|
@ -53,7 +53,10 @@ class SettingsAdHocCommand : public AdHocCommand {
|
|||
|
||||
class SettingsAdHocCommandFactory : public AdHocCommandFactory {
|
||||
public:
|
||||
SettingsAdHocCommandFactory() {}
|
||||
SettingsAdHocCommandFactory() {
|
||||
m_userSettings["send_headlines"] = "0";
|
||||
}
|
||||
|
||||
virtual ~SettingsAdHocCommandFactory() {}
|
||||
|
||||
AdHocCommand *createAdHocCommand(Component *component, UserManager *userManager, StorageBackend *storageBackend, const Swift::JID &initiator, const Swift::JID &to) {
|
||||
|
|
|
@ -116,6 +116,14 @@ class User : public Swift::EntityCapsProvider {
|
|||
return m_resources;
|
||||
}
|
||||
|
||||
void addUserSetting(const std::string &key, const std::string &value) {
|
||||
m_settings[key] = value;
|
||||
}
|
||||
|
||||
const std::string &getUserSetting(const std::string &key) {
|
||||
return m_settings[key];
|
||||
}
|
||||
|
||||
boost::signal<void ()> onReadyToConnect;
|
||||
boost::signal<void (Swift::Presence::ref presence)> onPresenceChanged;
|
||||
boost::signal<void (const Swift::JID &who, const std::string &room, const std::string &nickname, const std::string &password)> onRoomJoined;
|
||||
|
@ -145,6 +153,7 @@ class User : public Swift::EntityCapsProvider {
|
|||
int m_resources;
|
||||
int m_reconnectCounter;
|
||||
std::list<Swift::Presence::ref> m_joinedRooms;
|
||||
std::map<std::string, std::string> m_settings;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ AdHocManager::AdHocManager(Component *component, DiscoItemsResponder *discoItems
|
|||
m_collectTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(20);
|
||||
m_collectTimer->onTick.connect(boost::bind(&AdHocManager::removeOldSessions, this));
|
||||
m_collectTimer->start();
|
||||
|
||||
m_userManager->onUserCreated.connect(boost::bind(&AdHocManager::handleUserCreated, this, _1));
|
||||
}
|
||||
|
||||
AdHocManager::~AdHocManager() {
|
||||
|
@ -66,6 +68,21 @@ void AdHocManager::stop() {
|
|||
m_sessions.clear();
|
||||
}
|
||||
|
||||
void AdHocManager::handleUserCreated(User *user) {
|
||||
if (!m_storageBackend) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::map<std::string, AdHocCommandFactory *>::const_iterator it = m_factories.begin(); it != m_factories.end(); it++) {
|
||||
for (std::map<std::string, std::string>::const_iterator it2 = it->second->getUserSettings().begin(); it2 != it->second->getUserSettings().end(); it2++) {
|
||||
std::string value = CONFIG_STRING_DEFAULTED(m_component->getConfig(), it->second->getNode() + "." + it2->first, it2->second);
|
||||
int type = (int) TYPE_BOOLEAN;
|
||||
m_storageBackend->getUserSetting(user->getUserInfo().id, it2->first, type, value);
|
||||
user->addUserSetting(it2->first, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdHocManager::addAdHocCommand(AdHocCommandFactory *factory) {
|
||||
if (m_factories.find(factory->getNode()) != m_factories.end()) {
|
||||
LOG4CXX_ERROR(logger, "Command with node " << factory->getNode() << " is already registered. Ignoring this attempt.");
|
||||
|
@ -159,6 +176,12 @@ bool AdHocManager::handleSetRequest(const Swift::JID& from, const Swift::JID& to
|
|||
|
||||
// Command completed, so we can remove it now
|
||||
if (response->getStatus() == Swift::Command::Completed || response->getStatus() == Swift::Command::Canceled) {
|
||||
// update userSettings map if user is already connected
|
||||
User *user = m_userManager->getUser(from.toBare().toString());
|
||||
if (user) {
|
||||
handleUserCreated(user);
|
||||
}
|
||||
|
||||
m_sessions[from].erase(command->getId());
|
||||
if (m_sessions[from].empty()) {
|
||||
m_sessions.erase(from);
|
||||
|
|
|
@ -82,7 +82,14 @@ void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, con
|
|||
message->setType(Swift::Message::Groupchat);
|
||||
}
|
||||
else {
|
||||
message->setType(Swift::Message::Chat);
|
||||
if (message->getType() != Swift::Message::Headline) {
|
||||
if (m_conversationManager->getUser()->getUserSetting("send_headlines") == "1") {
|
||||
message->setType(Swift::Message::Headline);
|
||||
}
|
||||
else {
|
||||
message->setType(Swift::Message::Chat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string n = nickname;
|
||||
|
|
|
@ -39,12 +39,7 @@ ConversationManager::ConversationManager(User *user, Component *component){
|
|||
}
|
||||
|
||||
ConversationManager::~ConversationManager() {
|
||||
while(!m_convs.empty()) {
|
||||
LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Removing conversation " << (*m_convs.begin()).first);
|
||||
(*m_convs.begin()).second->destroyRoom();
|
||||
delete (*m_convs.begin()).second;
|
||||
m_convs.erase(m_convs.begin());
|
||||
}
|
||||
deleteAllConversations();
|
||||
}
|
||||
|
||||
void ConversationManager::deleteAllConversations() {
|
||||
|
|
|
@ -649,6 +649,10 @@ void NetworkPluginServer::handleConvMessagePayload(const std::string &data, bool
|
|||
msg->setBody(payload.message());
|
||||
}
|
||||
|
||||
if (payload.headline()) {
|
||||
msg->setType(Swift::Message::Headline);
|
||||
}
|
||||
|
||||
// Add xhtml-im payload.
|
||||
if (CONFIG_BOOL(m_config, "service.enable_xhtml") && !payload.xhtml().empty()) {
|
||||
msg->addPayload(boost::make_shared<Swift::XHTMLIMPayload>(payload.xhtml()));
|
||||
|
|
|
@ -40,6 +40,11 @@ SettingsAdHocCommand::SettingsAdHocCommand(Component *component, UserManager *us
|
|||
field->setName("enable_transport");
|
||||
field->setLabel("Enable transport");
|
||||
addFormField(field);
|
||||
|
||||
field = Swift::BooleanFormField::create(CONFIG_STRING_DEFAULTED(component->getConfig(), "settings.send_headlines", "0") == "1");
|
||||
field->setName("send_headlines");
|
||||
field->setLabel("Send messages as headlines");
|
||||
addFormField(field);
|
||||
}
|
||||
|
||||
SettingsAdHocCommand::~SettingsAdHocCommand() {
|
||||
|
|
|
@ -193,6 +193,15 @@ class TestingStorageBackend : public StorageBackend {
|
|||
settings[userId][variable] = value;
|
||||
}
|
||||
|
||||
void dumpUserSettings() {
|
||||
std::cout << "\n\nUserSettings dump:\n";
|
||||
for (std::map<int, std::map<std::string, std::string> >::const_iterator it = settings.begin(); it != settings.end(); it++) {
|
||||
for (std::map<std::string, std::string>::const_iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) {
|
||||
std::cout << it->first << ":" << it2->first << "=" << it2->second << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void beginTransaction() {}
|
||||
virtual void commitTransaction() {}
|
||||
};
|
||||
|
|
|
@ -24,6 +24,7 @@ using namespace Transport;
|
|||
class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
|
||||
CPPUNIT_TEST_SUITE(ConversationManagerTest);
|
||||
CPPUNIT_TEST(handleNormalMessages);
|
||||
CPPUNIT_TEST(handleNormalMessagesHeadline);
|
||||
CPPUNIT_TEST(handleGroupchatMessages);
|
||||
CPPUNIT_TEST(handleGroupchatMessagesTwoResources);
|
||||
CPPUNIT_TEST(handleChatstateMessages);
|
||||
|
@ -204,6 +205,55 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe
|
|||
received.clear();
|
||||
}
|
||||
|
||||
void handleNormalMessagesHeadline() {
|
||||
User *user = userManager->getUser("user@localhost");
|
||||
user->addUserSetting("send_headlines", "1");
|
||||
|
||||
TestingConversation *conv = new TestingConversation(user->getConversationManager(), "buddy1@test");
|
||||
user->getConversationManager()->addConversation(conv);
|
||||
conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2));
|
||||
|
||||
boost::shared_ptr<Swift::Message> msg(new Swift::Message());
|
||||
msg->setBody("hi there<>!");
|
||||
|
||||
// Forward it
|
||||
conv->handleMessage(msg);
|
||||
loop->processEvents();
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
|
||||
CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[0])));
|
||||
CPPUNIT_ASSERT_EQUAL(Swift::Message::Headline, dynamic_cast<Swift::Message *>(getStanza(received[0]))->getType());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("hi there<>!"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getBody());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getTo().toString());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40test@localhost/bot"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getFrom().toString());
|
||||
|
||||
received.clear();
|
||||
user->addUserSetting("send_headlines", "0");
|
||||
// Forward it - Conversation should keep the Headline type, because msg->getType() is Headline
|
||||
conv->handleMessage(msg);
|
||||
loop->processEvents();
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
|
||||
CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[0])));
|
||||
CPPUNIT_ASSERT_EQUAL(Swift::Message::Headline, dynamic_cast<Swift::Message *>(getStanza(received[0]))->getType());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("hi there<>!"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getBody());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getTo().toString());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40test@localhost/bot"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getFrom().toString());
|
||||
|
||||
received.clear();
|
||||
msg->setType(Swift::Message::Chat);
|
||||
// Forward it
|
||||
conv->handleMessage(msg);
|
||||
loop->processEvents();
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
|
||||
CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[0])));
|
||||
CPPUNIT_ASSERT_EQUAL(Swift::Message::Chat, dynamic_cast<Swift::Message *>(getStanza(received[0]))->getType());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("hi there<>!"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getBody());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getTo().toString());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40test@localhost/bot"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getFrom().toString());
|
||||
}
|
||||
|
||||
void handleGroupchatMessages() {
|
||||
User *user = userManager->getUser("user@localhost");
|
||||
TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true);
|
||||
|
|
|
@ -33,6 +33,8 @@ class SettingsAdHocCommandTest : public CPPUNIT_NS :: TestFixture, public BasicT
|
|||
CPPUNIT_TEST(executeBadSessionID);
|
||||
CPPUNIT_TEST(executeNotRegistered);
|
||||
CPPUNIT_TEST(cancel);
|
||||
CPPUNIT_TEST(propagateUserSetting);
|
||||
CPPUNIT_TEST(defaultAccordingToConfig);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
|
@ -327,6 +329,77 @@ class SettingsAdHocCommandTest : public CPPUNIT_NS :: TestFixture, public BasicT
|
|||
CPPUNIT_ASSERT_EQUAL(Swift::Command::Canceled, getStanza(received[0])->getPayload<Swift::Command>()->getStatus());
|
||||
}
|
||||
|
||||
void propagateUserSetting() {
|
||||
connectUser();
|
||||
User *user = userManager->getUser("user@localhost");
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("0"), user->getUserSetting("send_headlines"));
|
||||
|
||||
boost::shared_ptr<Swift::Command> payload(new Swift::Command("settings"));
|
||||
boost::shared_ptr<Swift::IQ> iq = Swift::IQ::createRequest(Swift::IQ::Set, Swift::JID("localhost"), "id", payload);
|
||||
iq->setFrom("user@localhost");
|
||||
injectIQ(iq);
|
||||
loop->processEvents();
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
|
||||
|
||||
CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
|
||||
CPPUNIT_ASSERT_EQUAL(Swift::IQ::Result, dynamic_cast<Swift::IQ *>(getStanza(received[0]))->getType());
|
||||
|
||||
CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::Command>());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("settings"), getStanza(received[0])->getPayload<Swift::Command>()->getNode());
|
||||
CPPUNIT_ASSERT_EQUAL(Swift::Command::Executing, getStanza(received[0])->getPayload<Swift::Command>()->getStatus());
|
||||
|
||||
// form element
|
||||
CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::Command>()->getForm());
|
||||
CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::Command>()->getForm()->getField("send_headlines"));
|
||||
|
||||
// set enabled_transport = 0
|
||||
Swift::FormField::ref f = getStanza(received[0])->getPayload<Swift:: Command>()->getForm()->getField("send_headlines");
|
||||
boost::dynamic_pointer_cast<Swift::BooleanFormField>(f)->setValue(true);
|
||||
|
||||
std::string sessionId = getStanza(received[0])->getPayload<Swift::Command>()->getSessionID();
|
||||
|
||||
// finish the command
|
||||
payload = boost::shared_ptr<Swift::Command>(new Swift::Command("settings"));
|
||||
payload->setSessionID(sessionId);
|
||||
payload->setForm(getStanza(received[0])->getPayload<Swift::Command>()->getForm());
|
||||
iq = Swift::IQ::createRequest(Swift::IQ::Set, Swift::JID("localhost"), "id", payload);
|
||||
iq->setFrom("user@localhost");
|
||||
received.clear();
|
||||
injectIQ(iq);
|
||||
loop->processEvents();
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("1"), user->getUserSetting("send_headlines"));
|
||||
}
|
||||
|
||||
void defaultAccordingToConfig() {
|
||||
std::istringstream ifs("service.server_mode = 1\nservice.jid_escaping=0\nservice.jid=localhost\nsettings.send_headlines=1\n");
|
||||
cfg->load(ifs);
|
||||
connectUser();
|
||||
User *user = userManager->getUser("user@localhost");
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("1"), user->getUserSetting("send_headlines"));
|
||||
boost::shared_ptr<Swift::Command> payload(new Swift::Command("settings"));
|
||||
boost::shared_ptr<Swift::IQ> iq = Swift::IQ::createRequest(Swift::IQ::Set, Swift::JID("localhost"), "id", payload);
|
||||
iq->setFrom("user@localhost");
|
||||
injectIQ(iq);
|
||||
loop->processEvents();
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
|
||||
|
||||
CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
|
||||
CPPUNIT_ASSERT_EQUAL(Swift::IQ::Result, dynamic_cast<Swift::IQ *>(getStanza(received[0]))->getType());
|
||||
|
||||
CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::Command>());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("settings"), getStanza(received[0])->getPayload<Swift::Command>()->getNode());
|
||||
CPPUNIT_ASSERT_EQUAL(Swift::Command::Executing, getStanza(received[0])->getPayload<Swift::Command>()->getStatus());
|
||||
|
||||
// form element
|
||||
CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::Command>()->getForm());
|
||||
CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::Command>()->getForm()->getField("send_headlines"));
|
||||
Swift::FormField::ref f = getStanza(received[0])->getPayload<Swift:: Command>()->getForm()->getField("send_headlines");
|
||||
CPPUNIT_ASSERT_EQUAL(true, boost::dynamic_pointer_cast<Swift::BooleanFormField>(f)->getValue());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION (SettingsAdHocCommandTest);
|
||||
|
|
Loading…
Add table
Reference in a new issue