Add channel sub-permission checks for admin/manage switches
This commit is contained in:
parent
d118fb17b8
commit
adf484b9df
9 changed files with 186 additions and 642 deletions
|
|
@ -170,11 +170,34 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
Creates a new channel (or destroys one you control).
|
||||
|
||||
## lock and unlock
|
||||
|
||||
Usage: channel/lock channelname = lockstring
|
||||
channel/unlock channelname = lockstring
|
||||
|
||||
Note: this is an admin command.
|
||||
|
||||
A lockstring is on the form locktype:lockfunc(). Channels understand three
|
||||
locktypes:
|
||||
listen - who may listen or join the channel.
|
||||
send - who may send messages to the channel
|
||||
control - who controls the channel. This is usually the one creating
|
||||
the channel.
|
||||
|
||||
Common lockfuncs are all() and perm(). To make a channel everyone can listen
|
||||
to but only builders can talk on, use this:
|
||||
|
||||
listen:all()
|
||||
send: perm(Builders)
|
||||
|
||||
"""
|
||||
key = "channel"
|
||||
aliases = ["chan", "channels"]
|
||||
locks = "cmd: not pperm(channel_banned)"
|
||||
help_category = "Comms"
|
||||
# these cmd: lock controls access to the channel command itself
|
||||
# the admin: lock controls access to /boot/ban/unban switches
|
||||
# the manage: lock controls access to /create/destroy/desc/lock/unlock switches
|
||||
locks = "cmd:not pperm(channel_banned);admin:all();manage:all();changelocks:perm(Admin)"
|
||||
switch_options = (
|
||||
"list", "all", "history", "sub", "unsub", "mute", "unmute", "alias", "unalias",
|
||||
"create", "destroy", "desc", "lock", "unlock", "boot", "ban", "unban", "who",)
|
||||
|
|
@ -186,6 +209,12 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
channel_msg_nick_alias = r"{alias}\s*?|{alias}\s+?(?P<arg1>.+?)"
|
||||
channel_msg_nick_replacement = "channel {channelname} = $1"
|
||||
|
||||
# to make it easier to override help functionality, we add the ability to
|
||||
# tweak access to different sub-functionality. Note that the system will
|
||||
# still check control lock etc even if you can use this functionality.
|
||||
# changing these does not change access to this command itself (that's the
|
||||
# locks property)
|
||||
|
||||
def search_channel(self, channelname, exact=False, handle_errors=True):
|
||||
"""
|
||||
Helper function for searching for a single channel with some error
|
||||
|
|
@ -721,20 +750,26 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
"""
|
||||
comtable = self.styled_table(
|
||||
"|wchannel|n",
|
||||
"|wmy aliases|n",
|
||||
"|wdescription|n",
|
||||
"channel",
|
||||
"my aliases",
|
||||
"locks",
|
||||
"description",
|
||||
align="l",
|
||||
maxwidth=_DEFAULT_WIDTH
|
||||
)
|
||||
|
||||
for chan in subscribed:
|
||||
|
||||
locks = "-"
|
||||
if chan.access(self.caller, "control"):
|
||||
locks = chan.locks
|
||||
|
||||
my_aliases = ", ".join(self.get_channel_aliases(chan))
|
||||
comtable.add_row(
|
||||
*("{}{}".format(
|
||||
chan.key,
|
||||
"({})".format(",".join(chan.aliases.all())) if chan.aliases.all() else ""),
|
||||
my_aliases,
|
||||
locks,
|
||||
chan.db.desc))
|
||||
return comtable
|
||||
|
||||
|
|
@ -744,7 +779,6 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
Args:
|
||||
subscribed (list): List of subscribed channels
|
||||
|
||||
Returns:
|
||||
EvTable: Table to display.
|
||||
|
||||
|
|
@ -752,33 +786,30 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
caller = self.caller
|
||||
|
||||
comtable = self.styled_table(
|
||||
"|wsub|n",
|
||||
"|wchannel|n",
|
||||
"|wmy aliases|n",
|
||||
"|wlocks|n",
|
||||
"|wdescription|n",
|
||||
"sub",
|
||||
"channel",
|
||||
"aliases",
|
||||
"my aliases",
|
||||
"description",
|
||||
maxwidth=_DEFAULT_WIDTH,
|
||||
)
|
||||
channels = subscribed + available
|
||||
|
||||
for chan in channels:
|
||||
my_aliases = ", ".join(self.get_channel_aliases(chan))
|
||||
if chan not in subscribed:
|
||||
substatus = "|rNo|n"
|
||||
elif caller in chan.mutelist:
|
||||
substatus = "|rMuting|n"
|
||||
else:
|
||||
substatus = "|gYes|n"
|
||||
my_aliases = ", ".join(self.get_channel_aliases(chan))
|
||||
comtable.add_row(
|
||||
*(substatus,
|
||||
"{}{}".format(
|
||||
chan.key,
|
||||
"({})".format(",".join(chan.aliases.all())) if chan.aliases.all() else ""),
|
||||
chan.key,
|
||||
",".join(chan.aliases.all()) if chan.aliases.all() else "",
|
||||
my_aliases,
|
||||
str(chan.locks),
|
||||
chan.db.desc))
|
||||
comtable.reformat_column(0, width=9)
|
||||
comtable.reformat_column(3, width=14)
|
||||
comtable.reformat_column(0, width=8)
|
||||
|
||||
return comtable
|
||||
|
||||
|
|
@ -819,6 +850,11 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
if 'create' in switches:
|
||||
# create a new channel
|
||||
|
||||
if not self.access(caller, "manage"):
|
||||
self.msg("You don't have access to use channel/create.")
|
||||
return
|
||||
|
||||
config = self.lhs
|
||||
if not config:
|
||||
self.msg("To create: channel/create name[;aliases][:typeclass] [= description]")
|
||||
|
|
@ -836,7 +872,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
if 'unalias' in switches:
|
||||
# remove a personal alias (no channel needed)
|
||||
alias = self.rhs
|
||||
alias = self.args.strip()
|
||||
if not alias:
|
||||
self.msg("Specify the alias to remove as channel/unalias <alias>")
|
||||
return
|
||||
|
|
@ -976,12 +1012,17 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
if 'destroy' in switches or 'delete' in switches:
|
||||
# destroy a channel we control
|
||||
reason = self.rhs or None
|
||||
|
||||
if not self.access(caller, "manage"):
|
||||
self.msg("You don't have access to use channel/destroy.")
|
||||
return
|
||||
|
||||
if not channel.access(caller, "control"):
|
||||
self.msg("You can only delete channels you control.")
|
||||
return
|
||||
|
||||
reason = self.rhs or None
|
||||
|
||||
def _perform_delete(caller, *args, **kwargs):
|
||||
self.destroy_channel(channel, message=reason)
|
||||
self.msg(f"Channel {channel.key} was successfully deleted.")
|
||||
|
|
@ -997,12 +1038,17 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
if 'desc' in switches:
|
||||
# set channel description
|
||||
desc = self.rhs.strip()
|
||||
|
||||
if not self.access(caller, "manage"):
|
||||
self.msg("You don't have access to use channel/desc.")
|
||||
return
|
||||
|
||||
if not channel.access(caller, "control"):
|
||||
self.msg("You can only change description of channels you control.")
|
||||
return
|
||||
|
||||
desc = self.rhs.strip()
|
||||
|
||||
if not desc:
|
||||
self.msg("Usage: /desc channel = description")
|
||||
return
|
||||
|
|
@ -1012,12 +1058,17 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
if 'lock' in switches:
|
||||
# add a lockstring to channel
|
||||
lockstring = self.rhs.strip()
|
||||
|
||||
if not self.access(caller, "changelocks"):
|
||||
self.msg("You don't have access to use channel/lock.")
|
||||
return
|
||||
|
||||
if not channel.access(caller, "control"):
|
||||
self.msg("You need 'control'-access to change locks on this channel.")
|
||||
return
|
||||
|
||||
lockstring = self.rhs.strip()
|
||||
|
||||
if not lockstring:
|
||||
self.msg("Usage: channel/lock channelname = lockstring")
|
||||
return
|
||||
|
|
@ -1031,16 +1082,21 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
if 'unlock' in switches:
|
||||
# remove/update lockstring from channel
|
||||
lockstring = self.rhs.strip()
|
||||
|
||||
if not lockstring:
|
||||
self.msg("Usage: channel/unlock channelname = lockstring")
|
||||
if not self.access(caller, "changelocks"):
|
||||
self.msg("You don't have access to use channel/unlock.")
|
||||
return
|
||||
|
||||
if not channel.access(caller, "control"):
|
||||
self.msg("You need 'control'-access to change locks on this channel.")
|
||||
return
|
||||
|
||||
lockstring = self.rhs.strip()
|
||||
|
||||
if not lockstring:
|
||||
self.msg("Usage: channel/unlock channelname = lockstring")
|
||||
return
|
||||
|
||||
success, err = self.unset_lock(channel, self.rhs)
|
||||
if success:
|
||||
self.msg("Removed lock from channel.")
|
||||
|
|
@ -1051,6 +1107,10 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
if 'boot' in switches:
|
||||
# boot a user from channel(s)
|
||||
|
||||
if not self.access(caller, "admin"):
|
||||
self.msg("You don't have access to use channel/boot.")
|
||||
return
|
||||
|
||||
if not self.rhs:
|
||||
self.msg("Usage: channel/boot channel[,channel,...] = username [:reason]")
|
||||
return
|
||||
|
|
@ -1095,6 +1155,10 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
if 'ban' in switches:
|
||||
# ban a user from channel(s)
|
||||
|
||||
if not self.access(caller, "admin"):
|
||||
self.msg("You don't have access to use channel/ban.")
|
||||
return
|
||||
|
||||
if not self.rhs:
|
||||
# view bans for channels
|
||||
|
||||
|
|
@ -1104,7 +1168,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
bans = ["Channel bans "
|
||||
"(to ban, use channel/ban channel[,channel,...] = username [:reason]"]
|
||||
bans.expand(self.channel_list_bans(channel))
|
||||
bans.extend(self.channel_list_bans(channel))
|
||||
self.msg("\n".join(bans))
|
||||
return
|
||||
|
||||
|
|
@ -1146,6 +1210,11 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
if 'unban' in switches:
|
||||
# unban a previously banned user from channel
|
||||
|
||||
if not self.access(caller, "admin"):
|
||||
self.msg("You don't have access to use channel/unban.")
|
||||
return
|
||||
|
||||
target_str = self.rhs.strip()
|
||||
|
||||
if not target_str:
|
||||
|
|
@ -1596,7 +1665,7 @@ class CmdClock(CmdChannel):
|
|||
|
||||
key = "clock"
|
||||
aliases = ["clock"]
|
||||
locks = "cmd:not pperm(channel_banned)"
|
||||
locks = "cmd:not pperm(channel_banned) and perm(Admin)"
|
||||
help_category = "Comms"
|
||||
|
||||
# this is used by the COMMAND_DEFAULT_CLASS parent
|
||||
|
|
@ -1705,7 +1774,7 @@ class CmdPage(COMMAND_DEFAULT_CLASS):
|
|||
caller = self.caller
|
||||
|
||||
# get the messages we've sent (not to channels)
|
||||
pages_we_sent = Msg.objects.get_messages_by_sender(caller, exclude_channel_messages=True)
|
||||
pages_we_sent = Msg.objects.get_messages_by_sender(caller)
|
||||
# get last messages we've got
|
||||
pages_we_got = Msg.objects.get_messages_by_receiver(caller)
|
||||
targets, message, number = [], None, None
|
||||
|
|
@ -1745,7 +1814,7 @@ class CmdPage(COMMAND_DEFAULT_CLASS):
|
|||
# a single-word message
|
||||
message = message[0].strip()
|
||||
|
||||
pages = pages_we_sent + pages_we_got
|
||||
pages = list(pages_we_sent) + list(pages_we_got)
|
||||
pages = sorted(pages, key=lambda page: page.date_created)
|
||||
|
||||
if message:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue