]> jfr.im git - irc/SurrealServices/srsv.git/blame - branches/0.5.0/modules/serviceslibs/adminserv.pm
Remove some debug lines
[irc/SurrealServices/srsv.git] / branches / 0.5.0 / modules / serviceslibs / adminserv.pm
CommitLineData
aecfa1fd 1# This file is part of SurrealServices.
2#
3# SurrealServices is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7#
8# SurrealServices is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with SurrealServices; if not, write to the Free Software
15# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16package adminserv;
17
18use strict;
19
20use SrSv::Agent;
21
22use SrSv::Text::Format qw(columnar);
23use SrSv::Errors;
24
25use SrSv::User qw(get_user_nick get_user_id);
26use SrSv::User::Notice;
27use SrSv::Help qw( sendhelp );
28
29use SrSv::Log;
30
31use SrSv::NickReg::Flags qw(NRF_NOHIGHLIGHT nr_chk_flag_user);
32
33use SrSv::MySQL '$dbh';
92c29160 34use Data::Dumper;
aecfa1fd 35use constant {
36 S_HELP => 1,
37 S_OPER => 2,
38 S_ADMIN => 3,
39 S_ROOT => 4,
40};
41
42our (%flags, @levels, @defflags, $allflags);
43
7d4055c0 44our $asnick_default = 'AdminServ1';
e6f09f48 45our $asnick = $asnick_default;
7b3a5814 46our $asuser = { NICK => $asnick, ID => ircd::getAgentUuid($asnick) };
e6f09f48 47
48our (@levels, @defflags);
aecfa1fd 49BEGIN {
50# BE CAREFUL CHANGING THESE
e6f09f48 51my @flagList = (
aecfa1fd 52 'SERVOP',
53 'FJOIN',
54 'SUPER',
55 'HOLD',
56 'FREEZE',
57 'BOT',
58 'QLINE',
59 'KILL',
60 'HELP',
61);
62
e6f09f48 63for(my $i = scalar(@flagList) - 1; $i >= 0; $i--) {
1e7fba35 64 $flags{$flagList[$i]} = 1 << $i;
aecfa1fd 65}
e6f09f48 66$allflags = (1 << scalar(@flagList)) - 1;
5e682044 67
e6f09f48 68@levels = ('Normal User', 'HelpOp', 'Operator', 'Administrator', 'Root');
aecfa1fd 69# BE CAREFUL CHANGING THESE
e6f09f48 70@defflags = (
aecfa1fd 71 0, # Unused
72 $flags{HELP}, # HelpOp
73 $flags{HELP}|$flags{FJOIN}|$flags{QLINE}|$flags{SUPER}|$flags{FREEZE}|$flags{KILL}, # Operator
74 $flags{HELP}|$flags{FJOIN}|$flags{QLINE}|$flags{SUPER}|$flags{FREEZE}|$flags{KILL}|
75 $flags{HOLD}|$flags{BOT}|$flags{SERVOP}, # Admin
76 $allflags # Root
77);
78
79}
aecfa1fd 80
81
82our (
83 $create_svsop, $delete_svsop, $rename_svsop,
84
85 $get_svs_list, $get_all_svsops,
86
87 $get_svs_level, $set_svs_level, $get_best_svs_level,
88
89 $chk_pass, $get_pass, $set_pass
90);
91
92sub init() {
1eb006d9 93 $asuser = { NICK => $asnick, ID => ircd::getAgentUuid($asnick) };
aecfa1fd 94 $create_svsop = $dbh->prepare("INSERT IGNORE INTO svsop SELECT id, NULL, NULL FROM nickreg WHERE nick=?");
95 $delete_svsop = $dbh->prepare("DELETE FROM svsop USING svsop, nickreg WHERE nickreg.nick=? AND svsop.nrid=nickreg.id");
96
97 $get_svs_list = $dbh->prepare("SELECT nickreg.nick, svsop.adder FROM svsop, nickreg WHERE svsop.level=? AND svsop.nrid=nickreg.id ORDER BY nickreg.nick");
98 $get_all_svsops = $dbh->prepare("SELECT nickreg.nick, svsop.level, svsop.adder FROM svsop, nickreg WHERE svsop.nrid=nickreg.id ORDER BY svsop.level, nickreg.nick");
99
100 $get_svs_level = $dbh->prepare("SELECT svsop.level FROM svsop, nickalias WHERE nickalias.alias=? AND svsop.nrid=nickalias.nrid");
101 $set_svs_level = $dbh->prepare("UPDATE svsop, nickreg SET svsop.level=?, svsop.adder=? WHERE nickreg.nick=? AND svsop.nrid=nickreg.id");
102 $get_best_svs_level = $dbh->prepare("SELECT svsop.level, nickreg.nick FROM nickid, nickreg, svsop WHERE nickid.nrid=nickreg.id AND svsop.nrid=nickreg.id AND nickid.id=? ORDER BY level DESC LIMIT 1");
103
104 $chk_pass = $dbh->prepare("SELECT 1 FROM ircop WHERE nick=? AND pass=?");
105 $get_pass = $dbh->prepare("SELECT pass FROM ircop WHERE nick=?");
106 $set_pass = $dbh->prepare("UPDATE ircop SET pass=? WHERE nick=?");
107}
108
109### ADMINSERV COMMANDS ###
110
111sub dispatch($$$) {
7b3a5814 112 $asuser = { NICK => $asnick, ID => ircd::getAgentUuid($asnick) };
5e682044 113 my ($user, $dstUser, $msg) = @_;
aecfa1fd 114 $msg =~ s/^\s+//;
115 my @args = split(/\s+/, $msg);
116 my $cmd = shift @args;
5e682044 117 return unless (lc $dstUser->{NICK} eq lc $asnick);
7b3a5814 118 $user -> {AGENT} = $asuser;
119 my $src = $user->{NICK};
5e682044 120 services::ulog($asuser, LOG_INFO(), "cmd: [$msg]", $user);
aecfa1fd 121
122 unless(is_svsop($user) or is_ircop($user)) {
123 notice($user, $err_deny);
5e682044 124 ircd::globops($asuser, "\002$src\002 failed access to $asnick $msg");
aecfa1fd 125 return;
126 }
127
128 if($cmd =~ /^svsop$/i) {
129 my $cmd2 = shift @args;
130
131 if($cmd2 =~ /^add$/i) {
132 if(@args == 2 and $args[1] =~ /^[aoh]$/i) {
133 as_svs_add($user, $args[0], num_level($args[1]));
134 } else {
135 notice($user, 'Syntax: SVSOP ADD <nick> <A|O|H>');
136 }
137 }
138 elsif($cmd2 =~ /^del$/i) {
139 if(@args == 1) {
140 as_svs_del($user, $args[0]);
141 } else {
142 notice($user, 'Syntax: SVSOP DEL <nick>');
143 }
144 }
145 elsif($cmd2 =~ /^list$/i) {
146 if(@args == 1 and $args[0] =~ /^[raoh]$/i) {
147 as_svs_list($user, num_level($args[0]));
148 } else {
149 notice($user, 'Syntax: SVSOP LIST <R|A|O|H>');
150 }
151 }
152 else {
153 notice($user, 'Syntax: SVSOP <ADD|DEL|LIST> [...]');
154 }
155 }
156 elsif($cmd =~ /^whois$/i) {
157 if(@args == 1) {
158 as_whois($user, $args[0]);
159 } else {
160 notice($user, 'Syntax: WHOIS <nick>');
161 }
162 }
163 elsif($cmd =~ /^help$/i) {
164 sendhelp($user, 'adminserv', @args)
165 }
166 elsif($cmd =~ /^staff$/i) {
167 if(@args == 0) {
168 as_staff($user);
169 }
170 else {
171 notice($user, 'Syntax: STAFF');
172 }
173 }
174 else {
175 notice($user, "Unrecognized command. For help, type: \002/msg adminserv help\002");
176 }
177}
178
179sub as_svs_add($$$) {
180 my ($user, $nick, $level) = @_;
181 my $src = get_user_nick($user);
182
183 my ($root, $oper) = validate_chg($user, $nick);
184 return unless $oper;
185
186 if(get_svs_level($root) >= S_ROOT) {
187 notice($user, $err_deny);
188 return;
189 }
190
191 $create_svsop->execute($root);
192 $set_svs_level->execute($level, $oper, $root);
193
194 notice($user, "\002$nick\002 is now a \002Services $levels[$level]\002.");
5e682044 195 wlog($asuser, LOG_INFO(), "$src added $root as a Services $levels[$level].");
aecfa1fd 196}
197
198sub as_svs_del($$) {
199 my ($user, $nick) = @_;
200 my $src = get_user_nick($user);
201
202 my ($root, $oper) = validate_chg($user, $nick);
203 return unless $oper;
204
205 if(get_svs_level($root) >= S_ROOT) {
206 notice($user, $err_deny);
207 return;
208 }
209
210 $delete_svsop->execute($root);
211 notice($user, "\002$nick\002 has been stripped of services rank.");
5e682044 212 wlog($asuser, LOG_INFO(), "$src stripped $root of services rank.")
aecfa1fd 213}
214
215sub as_svs_list($$) {
216 my ($user, $level) = @_;
217 my (@data, @reply);
218
219 $get_svs_list->execute($level);
220
221 while(my ($nick, $adder) = $get_svs_list->fetchrow_array) {
222 push @data, [$nick, "($adder)"];
223 }
224
225 notice($user, columnar({TITLE => "Services $levels[$level] list:",
226 NOHIGHLIGHT => nr_chk_flag_user($user, NRF_NOHIGHLIGHT)}, @data));
227}
228
229sub as_whois($$) {
230 my ($user, $nick) = @_;
231
232 my ($level, $root) = get_best_svs_level({ NICK => $nick });
233 notice($user, "\002$nick\002 is a Services $levels[$level]".($level ? ' due to identification to the nick '."\002$root\002." : ''));
234}
235
236sub as_staff($) {
237 my ($user) = @_;
238 my (@data);
239
240 $get_all_svsops->execute();
241
242 while(my ($nick, $level, $adder) = $get_all_svsops->fetchrow_array) {
243 push @data, [$nick, $levels[$level], "($adder)"];
244 }
245
246 notice($user, columnar({TITLE => 'Staff list:',
247 NOHIGHLIGHT => nr_chk_flag_user($user, NRF_NOHIGHLIGHT)}, @data));
248}
249
250
251### DATABASE UTILITY FUNCTIONS ###
252
253sub validate_chg($$) {
254 my ($user, $nick) = @_;
255 my ($oper);
256
257 unless($oper = is_svsop($user, S_ROOT)) {
258 notice($user, $err_deny);
259 return undef;
260 }
261
262 my $root = nickserv::get_root_nick($nick);
263 unless($root) {
264 notice($user, "The nick \002$nick\002 is not registered.");
265 return undef;
266 }
267
268 return ($root, $oper);
269}
270
271sub can_do($$) {
272 my ($user, $flag) = @_;
273 my $nflag = $flags{$flag};
274
275 my ($level, $nick) = get_best_svs_level($user);
aecfa1fd 276 if($defflags[$level] & $nflag) {
5e682044 277 return $nick if (($nflag == $flags{'HELP'}) or is_ircop($user));
aecfa1fd 278 }
279
280 return undef;
281}
282
283sub is_svsop($;$) {
284 my ($user, $rlev) = @_;
92c29160 285
aecfa1fd 286 my ($level, $nick) = get_best_svs_level($user);
92c29160 287 return $nick if (is_agent($nick)); #something odd with srsv kicking itself
aecfa1fd 288 return $nick if(defined($level) and !defined($rlev));
289
290 if($level >= $rlev) {
92c29160 291 return $nick if (($rlev == S_HELP) or is_ircop($user))
aecfa1fd 292 }
293
294 return undef;
295}
296
297sub is_ircop($) {
298 my ($user) = @_;
299
300 return undef if is_agent($user->{NICK});
301
302 return $user->{IRCOP} if(exists($user->{IRCOP}));
303
304 my %umodes = modes::splitumodes(nickserv::get_user_modes($user));
aecfa1fd 305 no warnings 'deprecated';
306 if(($umodes{'o'} eq '+') or ($umodes{'S'} eq '+')) {
307 $user->{IRCOP} = 1;
308 }
309 else {
310 $user->{IRCOP} = 0;
311 }
312
313 return $user->{IRCOP};
314}
315
316sub is_service($) {
317# detect if a user belongs to another service like NeoStats. only works if they set umode +S
318# is_ircop() includes is_service(), so no reason to call both.
319 my ($user) = @_;
320
321 return undef if is_agent($user->{NICK});
322
323 return $user->{SERVICE} if(exists($user->{SERVICE}));
324
325 my %umodes = modes::splitumodes(nickserv::get_user_modes($user));
326
327 if($umodes{'S'} eq '+') {
328 $user->{SERVICE} = 1;
329 $user->{IRCOP} = 1;
330 }
331 else {
332 $user->{SERVICE} = 0;
333 }
334
335 return $user->{SERVICE};
336}
337
338sub get_svs_level($) {
339 my ($nick) = @_;
340
341 return undef if is_agent($nick);
342
343 $get_svs_level->execute($nick);
344 my ($level) = $get_svs_level->fetchrow_array;
345
346 return $level or 0;
347}
348
349sub get_best_svs_level($) {
350 my ($user) = @_;
351
352 return undef if is_agent($user->{NICK});
353
354 if(exists($user->{SVSOP_LEVEL}) && exists($user->{SVSOP_NICK})) {
355 if(wantarray) {
356 return ($user->{SVSOP_LEVEL}, $user->{SVSOP_NICK});
357 } else {
358 return $user->{SVSOP_LEVEL};
359 }
360 }
361
362 my $uid = get_user_id($user);
363 $get_best_svs_level->execute($uid);
364 my ($level, $nick) = $get_best_svs_level->fetchrow_array;
365
366 $user->{SVSOP_LEVEL} = $level; $user->{SVSOP_NICK} = $nick;
367
368 if(wantarray) {
369 return ($level, $nick);
370 } else {
371 return $level;
372 }
373}
374
375### MISCELLANEA ###
376
377sub num_level($) {
378 my ($x) = @_;
379 $x =~ tr/hoarHOAR/12341234/;
380 return $x;
381}
382
383### IRC EVENTS ###
384
3851;