1
0
mirror of https://github.com/anope/anope.git synced 2026-06-19 01:04:46 +02:00
Files
anope/modules/sql_oper.cpp
T
Sadie Powell f9911dde52 Return references instead of pointers from the config system.
We used to return NULL from these methods but now we return an empty
block so this can never actually be null now.
2025-03-02 15:27:47 +00:00

182 lines
4.0 KiB
C++

/*
*
* (C) 2012-2025 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#include "module.h"
#include "modules/sql.h"
struct SQLOper final
: Oper
{
SQLOper(const Anope::string &n, OperType *o) : Oper(n, o) { }
};
class SQLOperResult final
: public SQL::Interface
{
Reference<User> user;
struct SQLOperResultDeleter final
{
SQLOperResult *res;
SQLOperResultDeleter(SQLOperResult *r) : res(r) { }
~SQLOperResultDeleter() { delete res; }
};
void Deoper()
{
if (user->Account() && user->Account()->o && dynamic_cast<SQLOper *>(user->Account()->o))
{
delete user->Account()->o;
user->Account()->o = NULL;
Log(this->owner) << "sql_oper: Removed services operator from " << user->nick << " (" << user->Account()->display << ")";
BotInfo *OperServ = Config->GetClient("OperServ");
user->RemoveMode(OperServ, "OPER"); // Probably not set, just incase
}
}
public:
SQLOperResult(Module *m, User *u) : SQL::Interface(m), user(u) { }
void OnResult(const SQL::Result &r) override
{
SQLOperResultDeleter d(this);
if (!user || !user->IsIdentified())
return;
if (r.Rows() == 0)
{
Log(LOG_DEBUG) << "sql_oper: Got 0 rows for " << user->nick;
Deoper();
return;
}
Anope::string opertype;
try
{
opertype = r.Get(0, "opertype");
}
catch (const SQL::Exception &)
{
Log(this->owner) << "Expected column named \"opertype\" but one was not found";
return;
}
Log(LOG_DEBUG) << "sql_oper: Got result for " << user->nick << ", opertype " << opertype;
Anope::string modes;
try
{
modes = r.Get(0, "modes");
}
catch (const SQL::Exception &)
{
// Common case here is an exception, but this probably doesn't get this far often
}
BotInfo *OperServ = Config->GetClient("OperServ");
if (opertype.empty())
{
Deoper();
return;
}
OperType *ot = OperType::Find(opertype);
if (ot == NULL)
{
Log(this->owner) << "sql_oper: Oper " << user->nick << " has type " << opertype << ", but this opertype does not exist?";
return;
}
if (user->Account()->o && !dynamic_cast<SQLOper *>(user->Account()->o))
{
Log(this->owner) << "Oper " << user->Account()->display << " has type " << opertype << ", but is already configured as an oper of type " << user->Account()->o->ot->GetName();
return;
}
if (!user->Account()->o || user->Account()->o->ot != ot)
{
Log(this->owner) << "sql_oper: Tieing oper " << user->nick << " to type " << opertype;
delete user->Account()->o;
user->Account()->o = new SQLOper(user->Account()->display, ot);
}
if (!user->HasMode("OPER"))
{
IRCD->SendOper(user);
if (!modes.empty())
user->SetModes(OperServ, modes);
}
}
void OnError(const SQL::Result &r) override
{
SQLOperResultDeleter d(this);
Log(this->owner) << "sql_oper: Error executing query " << r.GetQuery().query << ": " << r.GetError();
}
};
class ModuleSQLOper final
: public Module
{
Anope::string engine;
Anope::string query;
ServiceReference<SQL::Provider> SQL;
public:
ModuleSQLOper(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
{
}
~ModuleSQLOper()
{
for (const auto &[_, nc] : *NickCoreList)
{
if (nc->o && dynamic_cast<SQLOper *>(nc->o))
{
delete nc->o;
nc->o = NULL;
}
}
}
void OnReload(Configuration::Conf &conf) override
{
Configuration::Block &config = conf.GetModule(this);
this->engine = config.Get<const Anope::string>("engine");
this->query = config.Get<const Anope::string>("query");
this->SQL = ServiceReference<SQL::Provider>("SQL::Provider", this->engine);
}
void OnNickIdentify(User *u) override
{
if (!this->SQL)
{
Log() << "Unable to find SQL engine";
return;
}
SQL::Query q(this->query);
q.SetValue("a", u->Account()->display);
q.SetValue("i", u->ip.addr());
this->SQL->Run(new SQLOperResult(this, u), q);
Log(LOG_DEBUG) << "sql_oper: Checking authentication for " << u->Account()->display;
}
};
MODULE_INIT(ModuleSQLOper)