0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-09-06 08:45:20 +02:00
construct/modules/m_grant.c
Elizabeth Jennifer Myers 8aabb973c0 Implement chanroles, as discussed with nenolod.
The theory behind this is that services sends an ENCAP * GRANT #channel
UID :+flagspec message specifying the chanroles the user has. They are
mapped into flag bits and applied to the membership of the user. They
then are restricted or permitted to what they can do based on the
permissions mask regardless of rank.

For backwards compatibility, the default permission bit (without a GRANT
statement) allows a user to to anything an existing op can do ONLY if
they are an op.

Todo: make CHANROLE_STATUS work (the ability to apply +ov to people),
which is at the moment controlled by CHANROLE_MODE.
2011-07-06 13:46:22 -04:00

102 lines
2 KiB
C

/*
* charybdis: an advanced ircd
* m_grant: handle services grant commands
*/
#include "stdinc.h"
#include "client.h"
#include "ircd.h"
#include "numeric.h"
#include "s_serv.h"
#include "send.h"
#include "msg.h"
#include "parse.h"
#include "modules.h"
#include "s_conf.h"
#include "hash.h"
struct flag_list
{
char *name;
int flag;
};
static struct flag_list flaglist[] = {
{"kick", CHANROLE_KICK},
{"grant", CHANROLE_GRANT},
{"mode", CHANROLE_MODE},
{"topic", CHANROLE_TOPIC},
{"status", CHANROLE_STATUS},
{NULL, 0},
};
static int me_grant(struct Client *, struct Client *, int, const char **);
struct Message grant_msgtab = {
"GRANT", 0, 0, 0, MFLG_SLOW,
{mg_ignore, mg_ignore, mg_ignore, mg_ignore, {me_grant, 4}, mg_ignore}
};
mapi_clist_av1 grant_clist[] = { &grant_msgtab, NULL };
DECLARE_MODULE_AV1(grant, NULL, NULL, grant_clist, NULL, NULL, "Charybdis development team");
/*
* me_grant
*
* parv[1] = channel
* parv[2] = target UID
* parv[3] = flag spec
*/
static int
me_grant(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
struct Channel *chptr;
struct Client *target_p;
struct membership *msptr;
char *s, *t, *p;
if (!(chptr = find_channel(parv[1])))
return 0;
if (!(target_p = find_person(parv[2])))
return 0;
/* Makes no sense to do this for non-local users */
if(!MyClient(target_p))
return 0;
if (!(msptr = find_channel_membership(chptr, target_p)))
return 0;
/* Unset */
RemoveChanRole(msptr, CHANROLE_UNSET);
t = LOCAL_COPY(parv[3]);
for (s = rb_strtok_r(t, " ", &p); s; s = rb_strtok_r(NULL, " ", &p))
{
const char *priv = s + 1; /* The actual priv */
struct flag_list *fl;
int flag = 0;
/* Go through the flags list... */
for(fl = flaglist; fl->name != NULL; fl++)
{
if (strcasecmp(fl->name, priv) == 0)
{
flag = fl->flag;
break;
}
}
/* Ack no flag! */
if (!flag)
continue;
if (s[0] == '-')
RemoveChanRole(msptr, flag);
else if (s[0] == '+')
SetChanRole(msptr, flag);
}
return 0;
}