@@ -15,6 +15,9 @@ Version 6.0
|
|||||||
supported.
|
supported.
|
||||||
- Invitations can now be sent to any JID, not only JIDs served by the biboumi
|
- Invitations can now be sent to any JID, not only JIDs served by the biboumi
|
||||||
instance itself.
|
instance itself.
|
||||||
|
- The persistent_by_default configuration option has been added, this
|
||||||
|
lets the administrator decide whether or not the rooms should be
|
||||||
|
persistent or not by default, for all users.
|
||||||
|
|
||||||
Version 5.0 - 2017-05-24
|
Version 5.0 - 2017-05-24
|
||||||
========================
|
========================
|
||||||
|
|||||||
+22
-4
@@ -100,6 +100,21 @@ be used by an administrator that just wants to let their users join their own
|
|||||||
IRC server using an XMPP client, while forbidding access to any other IRC
|
IRC server using an XMPP client, while forbidding access to any other IRC
|
||||||
server.
|
server.
|
||||||
|
|
||||||
|
persistent_by_default
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
If this option is set to `true`, all rooms will be persistent by default:
|
||||||
|
the value of the “persistent” option in the global configuration of each
|
||||||
|
user will be “true”, but the value of each individual room will still
|
||||||
|
default to false. This means that a user just needs to change the global
|
||||||
|
“persistent” configuration option to false in order to override this.
|
||||||
|
|
||||||
|
If it is set to false (the default value), all rooms are not persistent by
|
||||||
|
default.
|
||||||
|
|
||||||
|
Each room can be configured individually by each user, to override this
|
||||||
|
default value. See `Ad-hoc commands`_.
|
||||||
|
|
||||||
realname_customization
|
realname_customization
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
@@ -595,10 +610,13 @@ On the gateway itself (e.g on the JID biboumi.example.com):
|
|||||||
the database.
|
the database.
|
||||||
* Max history length: The maximum number of lines in the history
|
* Max history length: The maximum number of lines in the history
|
||||||
that the server is allowed to send when joining a channel.
|
that the server is allowed to send when joining a channel.
|
||||||
* Persistent: Overrides the value specified in each individual channel,
|
|
||||||
all channels are persistent, whether or not their specific value is
|
* Persistent: Overrides the value specified in each individual channel.
|
||||||
true or false. See below for more details on what a persistent
|
If this option is set to true, all channels are persistent, whether
|
||||||
channel is.
|
or not their specific value is true or false. This option is true by
|
||||||
|
default for everyone if the `persistent_by_default` configuration
|
||||||
|
option is true, otherwise it’s false. See below for more details on
|
||||||
|
what a persistent channel is. This value is
|
||||||
|
|
||||||
On a server JID (e.g on the JID chat.freenode.org@biboumi.example.com)
|
On a server JID (e.g on the JID chat.freenode.org@biboumi.example.com)
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|||||||
@@ -435,7 +435,7 @@ void Bridge::leave_irc_channel(Iid&& iid, const std::string& status_message, con
|
|||||||
bool persistent = false;
|
bool persistent = false;
|
||||||
#ifdef USE_DATABASE
|
#ifdef USE_DATABASE
|
||||||
const auto goptions = Database::get_global_options(this->user_jid);
|
const auto goptions = Database::get_global_options(this->user_jid);
|
||||||
if (goptions.col<Database::Persistent>())
|
if (goptions.col<Database::GlobalPersistent>())
|
||||||
persistent = true;
|
persistent = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ std::string Config::get(const std::string& option, const std::string& def)
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Config::get_bool(const std::string& option, const bool def)
|
||||||
|
{
|
||||||
|
auto res = Config::get(option, "");
|
||||||
|
if (res.empty())
|
||||||
|
return def;
|
||||||
|
return res == "true";
|
||||||
|
}
|
||||||
|
|
||||||
int Config::get_int(const std::string& option, const int& def)
|
int Config::get_int(const std::string& option, const int& def)
|
||||||
{
|
{
|
||||||
std::string res = Config::get(option, "");
|
std::string res = Config::get(option, "");
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ public:
|
|||||||
* the second argument as the default.
|
* the second argument as the default.
|
||||||
*/
|
*/
|
||||||
static int get_int(const std::string&, const int&);
|
static int get_int(const std::string&, const int&);
|
||||||
|
static bool get_bool(const std::string&, const bool);
|
||||||
/**
|
/**
|
||||||
* Set a value for the given option. And write all the config
|
* Set a value for the given option. And write all the config
|
||||||
* in the file from which it was read if save is true.
|
* in the file from which it was read if save is true.
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <utils/get_first_non_empty.hpp>
|
#include <utils/get_first_non_empty.hpp>
|
||||||
#include <utils/time.hpp>
|
#include <utils/time.hpp>
|
||||||
|
|
||||||
|
#include <config/config.hpp>
|
||||||
|
|
||||||
#include <database/index.hpp>
|
#include <database/index.hpp>
|
||||||
|
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
@@ -18,6 +20,9 @@ Database::IrcChannelOptionsTable Database::irc_channel_options("IrcChannelOption
|
|||||||
Database::RosterTable Database::roster("roster");
|
Database::RosterTable Database::roster("roster");
|
||||||
std::map<Database::CacheKey, Database::EncodingIn::real_type> Database::encoding_in_cache{};
|
std::map<Database::CacheKey, Database::EncodingIn::real_type> Database::encoding_in_cache{};
|
||||||
|
|
||||||
|
Database::GlobalPersistent::GlobalPersistent():
|
||||||
|
Column<bool>{Config::get_bool("persistent_by_default", false)}
|
||||||
|
{}
|
||||||
|
|
||||||
void Database::open(const std::string& filename)
|
void Database::open(const std::string& filename)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ class Database
|
|||||||
struct Persistent: Column<bool> { static constexpr auto name = "persistent_";
|
struct Persistent: Column<bool> { static constexpr auto name = "persistent_";
|
||||||
Persistent(): Column<bool>(false) {} };
|
Persistent(): Column<bool>(false) {} };
|
||||||
|
|
||||||
|
struct GlobalPersistent: Column<bool> { static constexpr auto name = "persistent_";
|
||||||
|
GlobalPersistent(); };
|
||||||
|
|
||||||
struct LocalJid: Column<std::string> { static constexpr auto name = "local"; };
|
struct LocalJid: Column<std::string> { static constexpr auto name = "local"; };
|
||||||
|
|
||||||
struct RemoteJid: Column<std::string> { static constexpr auto name = "remote"; };
|
struct RemoteJid: Column<std::string> { static constexpr auto name = "remote"; };
|
||||||
@@ -81,7 +84,7 @@ class Database
|
|||||||
using MucLogLineTable = Table<Id, Uuid, Owner, IrcChanName, IrcServerName, Date, Body, Nick>;
|
using MucLogLineTable = Table<Id, Uuid, Owner, IrcChanName, IrcServerName, Date, Body, Nick>;
|
||||||
using MucLogLine = MucLogLineTable::RowType;
|
using MucLogLine = MucLogLineTable::RowType;
|
||||||
|
|
||||||
using GlobalOptionsTable = Table<Id, Owner, MaxHistoryLength, RecordHistory, Persistent>;
|
using GlobalOptionsTable = Table<Id, Owner, MaxHistoryLength, RecordHistory, GlobalPersistent>;
|
||||||
using GlobalOptions = GlobalOptionsTable::RowType;
|
using GlobalOptions = GlobalOptionsTable::RowType;
|
||||||
|
|
||||||
using IrcServerOptionsTable = Table<Id, Owner, Server, Pass, AfterConnectionCommand, TlsPorts, Ports, Username, Realname, VerifyCert, TrustedFingerprint, EncodingOut, EncodingIn, MaxHistoryLength>;
|
using IrcServerOptionsTable = Table<Id, Owner, Server, Pass, AfterConnectionCommand, TlsPorts, Ports, Username, Realname, VerifyCert, TrustedFingerprint, EncodingOut, EncodingIn, MaxHistoryLength>;
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ void ConfigureGlobalStep1(XmppComponent&, AdhocSession& session, XmlNode& comman
|
|||||||
{
|
{
|
||||||
XmlSubNode value(persistent, "value");
|
XmlSubNode value(persistent, "value");
|
||||||
value.set_name("value");
|
value.set_name("value");
|
||||||
if (options.col<Database::Persistent>())
|
if (options.col<Database::GlobalPersistent>())
|
||||||
value.set_inner("true");
|
value.set_inner("true");
|
||||||
else
|
else
|
||||||
value.set_inner("false");
|
value.set_inner("false");
|
||||||
@@ -193,7 +193,7 @@ void ConfigureGlobalStep2(XmppComponent& xmpp_component, AdhocSession& session,
|
|||||||
}
|
}
|
||||||
else if (field->get_tag("var") == "persistent" &&
|
else if (field->get_tag("var") == "persistent" &&
|
||||||
value)
|
value)
|
||||||
options.col<Database::Persistent>() = to_bool(value->get_inner());
|
options.col<Database::GlobalPersistent>() = to_bool(value->get_inner());
|
||||||
}
|
}
|
||||||
|
|
||||||
options.save(Database::db);
|
options.save(Database::db);
|
||||||
|
|||||||
@@ -377,7 +377,15 @@ port=8811
|
|||||||
fixed_irc_server=irc.localhost
|
fixed_irc_server=irc.localhost
|
||||||
admin=admin@example.com
|
admin=admin@example.com
|
||||||
identd_port=1113
|
identd_port=1113
|
||||||
"""}
|
""",
|
||||||
|
|
||||||
|
'persistent_by_default':
|
||||||
|
"""hostname=biboumi.localhost
|
||||||
|
password=coucou
|
||||||
|
db_name=e2e_test.sqlite
|
||||||
|
port=8811
|
||||||
|
persistent_by_default=true
|
||||||
|
""",}
|
||||||
|
|
||||||
common_replacements = {
|
common_replacements = {
|
||||||
'irc_server_one': 'irc.localhost@biboumi.localhost',
|
'irc_server_one': 'irc.localhost@biboumi.localhost',
|
||||||
@@ -2650,6 +2658,7 @@ if __name__ == '__main__':
|
|||||||
"/iq/commands:command/dataform:x[@type='form']/dataform:instructions[text()='Edit the form, to configure your global settings for the component.']",
|
"/iq/commands:command/dataform:x[@type='form']/dataform:instructions[text()='Edit the form, to configure your global settings for the component.']",
|
||||||
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='max_history_length']/dataform:value[text()='20']",
|
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='max_history_length']/dataform:value[text()='20']",
|
||||||
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='boolean'][@var='record_history']/dataform:value[text()='true']",
|
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='boolean'][@var='record_history']/dataform:value[text()='true']",
|
||||||
|
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='boolean'][@var='persistent']/dataform:value[text()='false']",
|
||||||
"/iq/commands:command/commands:actions/commands:next",
|
"/iq/commands:command/commands:actions/commands:next",
|
||||||
),
|
),
|
||||||
after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid"))
|
after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid"))
|
||||||
@@ -2671,6 +2680,20 @@ if __name__ == '__main__':
|
|||||||
partial(send_stanza, "<iq type='set' id='id4' from='{jid_one}/{resource_one}' to='{biboumi_host}'><command xmlns='http://jabber.org/protocol/commands' action='cancel' node='configure' sessionid='{sessionid}' /></iq>"),
|
partial(send_stanza, "<iq type='set' id='id4' from='{jid_one}/{resource_one}' to='{biboumi_host}'><command xmlns='http://jabber.org/protocol/commands' action='cancel' node='configure' sessionid='{sessionid}' /></iq>"),
|
||||||
partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='canceled']"),
|
partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='canceled']"),
|
||||||
]),
|
]),
|
||||||
|
Scenario("global_configure_persistent_by_default",
|
||||||
|
[
|
||||||
|
handshake_sequence(),
|
||||||
|
partial(send_stanza, "<iq type='set' id='id1' from='{jid_one}/{resource_one}' to='{biboumi_host}'><command xmlns='http://jabber.org/protocol/commands' node='configure' action='execute' /></iq>"),
|
||||||
|
partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='configure'][@sessionid][@status='executing']",
|
||||||
|
"/iq/commands:command/dataform:x[@type='form']/dataform:title[text()='Configure some global default settings.']",
|
||||||
|
"/iq/commands:command/dataform:x[@type='form']/dataform:instructions[text()='Edit the form, to configure your global settings for the component.']",
|
||||||
|
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='max_history_length']/dataform:value[text()='20']",
|
||||||
|
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='boolean'][@var='record_history']/dataform:value[text()='true']",
|
||||||
|
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='boolean'][@var='persistent']/dataform:value[text()='true']",
|
||||||
|
"/iq/commands:command/commands:actions/commands:next",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],conf='persistent_by_default'),
|
||||||
Scenario("irc_server_configure",
|
Scenario("irc_server_configure",
|
||||||
[
|
[
|
||||||
handshake_sequence(),
|
handshake_sequence(),
|
||||||
|
|||||||
Reference in New Issue
Block a user