Commit e75d7ad8 authored by louiz’'s avatar louiz’

Add a Record History option in the Channel configuration form

fix #3269
parent 40db183e
Pipeline #777 passed with stages
in 19 minutes and 42 seconds
......@@ -3,6 +3,8 @@ Version 6.0
- The LiteSQL dependency was removed. Only libsqlite3 is now necessary
to work with the database.
- The RecordHistory option can now also be configured for each IRC channel,
individually.
Version 5.0 - 2017-05-24
========================
......
......@@ -358,7 +358,7 @@ History
-------
Public channel messages are saved into archives, inside the database, unless
the `record_history` option is set to false for that user `Ad-hoc commands`.
the `record_history` option is set to false by that user (see `Ad-hoc commands`).
Private messages (messages that are sent directly to a nickname, not a
channel) are never stored in the database. When a channel is joined, biboumi
sends the `max_history_length` messages found in the database as the MUC
......@@ -631,6 +631,11 @@ On a channel JID (e.g on the JID #test%chat.freenode.org@biboumi.example.com)
the archiving of messages is enabled for this room, the client will
receive the messages that where sent in this channel. This option can be
used to make biboumi act as an IRC bouncer.
* Record History: whether or not history messages should be saved in
the database, for this specific channel. If the value is “unset” (the
default), then the value configured globally is used. This option is there,
for example, to be able to enable history recording globally while disabling
it for a few specific “private” channels.
Raw IRC messages
----------------
......
......@@ -20,6 +20,16 @@ struct OptionalBool
this->is_set = false;
}
std::string to_string()
{
if (this->is_set == false)
return "unset";
else if (this->value)
return "true";
else
return "false";
}
bool is_set{false};
bool value{false};
};
......@@ -434,6 +434,26 @@ void insert_irc_channel_configuration_form(XmlNode& node, const Jid& requester,
XmlSubNode instructions(x, "instructions");
instructions.set_inner("Edit the form, to configure the settings of the IRC channel "s + iid.get_local());
XmlSubNode record_history(x, "field");
record_history["var"] = "record_history";
record_history["type"] = "list-single";
record_history["label"] = "Record history for this channel";
record_history["desc"] = "If unset, the value is the one configured globally";
{
// Value selected by default
XmlSubNode value(record_history, "value");
value.set_inner(options.col<Database::RecordHistoryOptional>().to_string());
}
// All three possible values
for (const auto& val: {"unset", "true", "false"})
{
XmlSubNode option(record_history, "option");
option["label"] = val;
XmlSubNode value(option, "value");
value.set_inner(val);
}
XmlSubNode encoding_out(x, "field");
encoding_out["var"] = "encoding_out";
encoding_out["type"] = "text-single";
......@@ -471,12 +491,12 @@ void insert_irc_channel_configuration_form(XmlNode& node, const Jid& requester,
}
}
void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node)
void ConfigureIrcChannelStep2(XmppComponent& xmpp_component, AdhocSession& session, XmlNode& command_node)
{
const Jid owner(session.get_owner_jid());
const Jid target(session.get_target_jid());
if (handle_irc_channel_configuration_form(command_node, owner, target))
if (handle_irc_channel_configuration_form(xmpp_component, command_node, owner, target))
{
command_node.delete_all_children();
XmlSubNode note(command_node, "note");
......@@ -492,7 +512,7 @@ void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& co
}
}
bool handle_irc_channel_configuration_form(const XmlNode& node, const Jid& requester, const Jid& target)
bool handle_irc_channel_configuration_form(XmppComponent& xmpp_component, const XmlNode& node, const Jid& requester, const Jid& target)
{
const XmlNode* x = node.get_child("x", "jabber:x:data");
if (x)
......@@ -500,7 +520,7 @@ bool handle_irc_channel_configuration_form(const XmlNode& node, const Jid& reque
if (x->get_tag("type") == "submit")
{
const Iid iid(target.local, {});
auto options = Database::get_irc_channel_options(requester.local + "@" + requester.domain,
auto options = Database::get_irc_channel_options(requester.bare(),
iid.get_server(), iid.get_local());
for (const XmlNode *field: x->get_children("field", "jabber:x:data"))
{
......@@ -517,6 +537,31 @@ bool handle_irc_channel_configuration_form(const XmlNode& node, const Jid& reque
else if (field->get_tag("var") == "persistent" &&
value)
options.col<Database::Persistent>() = to_bool(value->get_inner());
else if (field->get_tag("var") == "record_history" &&
value && !value->get_inner().empty())
{
OptionalBool& database_value = options.col<Database::RecordHistoryOptional>();
if (value->get_inner() == "true")
database_value.set_value(true);
else if (value->get_inner() == "false")
database_value.set_value(false);
else
database_value.unset();
auto& biboumi_component = dynamic_cast<BiboumiComponent&>(xmpp_component);
Bridge* bridge = biboumi_component.find_user_bridge(requester.bare());
if (bridge)
{
if (database_value.is_set)
bridge->set_record_history(database_value.value);
else
{ // It is unset, we need to fetch the Global option, to
// know if it’s enabled or not
auto g_options = Database::get_global_options(requester.bare());
bridge->set_record_history(g_options.col<Database::RecordHistory>());
}
}
}
}
options.save(Database::db);
......
......@@ -20,7 +20,7 @@ void ConfigureIrcServerStep2(XmppComponent&, AdhocSession& session, XmlNode& com
void ConfigureIrcChannelStep1(XmppComponent&, AdhocSession& session, XmlNode& command_node);
void insert_irc_channel_configuration_form(XmlNode& node, const Jid& requester, const Jid& target);
void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);
bool handle_irc_channel_configuration_form(const XmlNode& node, const Jid& requester, const Jid& target);
bool handle_irc_channel_configuration_form(XmppComponent&, const XmlNode& node, const Jid& requester, const Jid& target);
void DisconnectUserFromServerStep1(XmppComponent&, AdhocSession& session, XmlNode& command_node);
void DisconnectUserFromServerStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);
......
......@@ -719,7 +719,7 @@ bool BiboumiComponent::handle_room_configuration_form(const XmlNode& query, cons
return false;
Jid requester(from);
if (!handle_irc_channel_configuration_form(query, requester, to))
if (!handle_irc_channel_configuration_form(*this, query, requester, to))
return false;
Stanza iq("iq");
......
......@@ -2467,6 +2467,7 @@ if __name__ == '__main__':
partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='configure'][@sessionid][@status='executing']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_out']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='list-single'][@var='record_history']/dataform:value[text()='unset']",
),
after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid"))
),
......@@ -2476,6 +2477,7 @@ if __name__ == '__main__':
"<field var='ports' />"
"<field var='encoding_out'><value>UTF-8</value></field>"
"<field var='encoding_in'><value>latin-1</value></field>"
"<field var='record_history'><value>true</value></field>"
"</x></command></iq>"),
partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='completed']/commands:note[@type='info'][text()='Configuration successfully applied.']"),
......@@ -2484,6 +2486,7 @@ if __name__ == '__main__':
"/iq/commands:command/dataform:x[@type='form']/dataform:title[text()='Configure the IRC channel #foo on server irc.localhost']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']/dataform:value[text()='latin-1']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_out']/dataform:value[text()='UTF-8']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='list-single'][@var='record_history']/dataform:value[text()='true']",
"/iq/commands:command/commands:actions/commands:next",
),
after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid"))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment