.BANCHO. New privileges system, add restricted mode

This commit is contained in:
Nyo 2016-07-03 20:51:19 +02:00
parent 99276d83b3
commit 6ac3b853f4
16 changed files with 291 additions and 116 deletions

View File

@ -74,3 +74,6 @@ class userSilencedException(Exception):
class need2FAException(Exception): class need2FAException(Exception):
pass pass
class userRestrictedException(Exception):
pass

View File

@ -11,6 +11,7 @@ from constants import mods
from helpers import generalFunctions from helpers import generalFunctions
from helpers import logHelper as log from helpers import logHelper as log
from constants import gameModes from constants import gameModes
from constants import privileges
""" """
Commands callbacks Commands callbacks
@ -98,7 +99,7 @@ def kickAll(fro, chan, message):
# Kick everyone but mods/admins # Kick everyone but mods/admins
toKick = [] toKick = []
for key, value in glob.tokens.tokens.items(): for key, value in glob.tokens.tokens.items():
if value.rank < 3: if value.admin == False:
toKick.append(key) toKick.append(key)
# Loop though users to kick (we can't change dictionary size while iterating) # Loop though users to kick (we can't change dictionary size while iterating)
@ -213,7 +214,7 @@ def ban(fro, chan, message):
return "{}: user not found".format(target) return "{}: user not found".format(target)
# Set allowed to 0 # Set allowed to 0
userHelper.setAllowed(targetUserID, 0) userHelper.ban(targetUserID)
# Send ban packet to the user if he's online # Send ban packet to the user if he's online
targetToken = glob.tokens.getTokenFromUsername(target) targetToken = glob.tokens.getTokenFromUsername(target)
@ -236,11 +237,52 @@ def unban(fro, chan, message):
return "{}: user not found".format(target) return "{}: user not found".format(target)
# Set allowed to 1 # Set allowed to 1
userHelper.setAllowed(targetUserID, 1) userHelper.unban(targetUserID)
log.rap(userID, "has unbanned {}".format(target), True) log.rap(userID, "has unbanned {}".format(target), True)
return "Welcome back {}!".format(target) return "Welcome back {}!".format(target)
def restrict(fro, chan, message):
# Get parameters
for i in message:
i = i.lower()
target = message[0].replace("_", " ")
# Make sure the user exists
targetUserID = userHelper.getID(target)
userID = userHelper.getID(fro)
if targetUserID == False:
return "{}: user not found".format(target)
# Put this user in restricted mode
userHelper.restrict(targetUserID)
# Send restricted mode packet to this user if he's online
targetToken = glob.tokens.getTokenFromUsername(target)
if targetToken != None:
targetToken.setRestricted()
log.rap(userID, "has put {} in restricted mode".format(target), True)
return "Bye bye {}. See you later, maybe.".format(target)
def unrestrict(fro, chan, message):
# Get parameters
for i in message:
i = i.lower()
target = message[0].replace("_", " ")
# Make sure the user exists
targetUserID = userHelper.getID(target)
userID = userHelper.getID(fro)
if targetUserID == False:
return "{}: user not found".format(target)
# Set allowed to 1
userHelper.unrestrict(targetUserID)
log.rap(userID, "has removed restricted mode from {}".format(target), True)
return "Welcome back {}!".format(target)
def restartShutdown(restart): def restartShutdown(restart):
"""Restart (if restart = True) or shutdown (if restart = False) pep.py safely""" """Restart (if restart = True) or shutdown (if restart = False) pep.py safely"""
msg = "We are performing some maintenance. Bancho will {} in 5 seconds. Thank you for your patience.".format("restart" if restart else "shutdown") msg = "We are performing some maintenance. Bancho will {} in 5 seconds. Thank you for your patience.".format("restart" if restart else "shutdown")
@ -287,7 +329,7 @@ def systemMaintenance(fro, chan, message):
# Disconnect everyone but mod/admins # Disconnect everyone but mod/admins
for _, value in glob.tokens.tokens.items(): for _, value in glob.tokens.tokens.items():
if value.rank < 3: if value.admin == False:
who.append(value.userID) who.append(value.userID)
glob.tokens.enqueueAll(serverPackets.notification("Our bancho server is in maintenance mode. Please try to login again later.")) glob.tokens.enqueueAll(serverPackets.notification("Our bancho server is in maintenance mode. Please try to login again later."))
@ -306,7 +348,7 @@ def systemStatus(fro, chan, message):
data = systemHelper.getSystemInfo() data = systemHelper.getSystemInfo()
# Final message # Final message
msg = "pep.py bancho server v{}\n".format(glob.VERSION) msg = "pep.py bancho server v{}".format(glob.VERSION)
msg += "made by the Ripple team\n" msg += "made by the Ripple team\n"
msg += "\n" msg += "\n"
msg += "=== BANCHO STATS ===\n" msg += "=== BANCHO STATS ===\n"
@ -555,14 +597,7 @@ trigger: message that triggers the command
callback: function to call when the command is triggered. Optional. callback: function to call when the command is triggered. Optional.
response: text to return when the command is triggered. Optional. response: text to return when the command is triggered. Optional.
syntax: command syntax. Arguments must be separated by spaces (eg: <arg1> <arg2>) syntax: command syntax. Arguments must be separated by spaces (eg: <arg1> <arg2>)
minRank: minimum rank to execute that command. Optional (default = 1) privileges: privileges needed to execute the command. Optional.
rank: EXACT rank used to execute that command. Optional.
RANKS:
1: Normal user
2: Supporter
3: Developer
4: Community manager
NOTES: NOTES:
- You CAN'T use both rank and minRank at the same time. - You CAN'T use both rank and minRank at the same time.
@ -593,70 +628,80 @@ commands = [
}, { }, {
"trigger": "!alert", "trigger": "!alert",
"syntax": "<message>", "syntax": "<message>",
"minRank": 3, "privileges": privileges.ADMIN_SEND_ALERTS,
"callback": alert "callback": alert
}, { }, {
"trigger": "!alertuser", "trigger": "!alertuser",
"syntax": "<username> <message>", "syntax": "<username> <message>",
"minRank": 3, "privileges": privileges.ADMIN_SEND_ALERTS,
"callback": alertUser, "callback": alertUser,
}, { }, {
"trigger": "!moderated", "trigger": "!moderated",
"minRank": 3, "privileges": privileges.ADMIN_CHAT_MOD,
"callback": moderated "callback": moderated
}, { }, {
"trigger": "!kickall", "trigger": "!kickall",
"rank": 3, "privileges": privileges.ADMIN_KICK_USERS,
"callback": kickAll "callback": kickAll
}, { }, {
"trigger": "!kick", "trigger": "!kick",
"syntax": "<target>", "syntax": "<target>",
"minRank": 3, "privileges": privileges.ADMIN_KICK_USERS,
"callback": kick "callback": kick
}, { }, {
"trigger": "!fokabot reconnect", "trigger": "!fokabot reconnect",
"minRank": 3, "privileges": privileges.ADMIN_MANAGE_SERVERS,
"callback": fokabotReconnect "callback": fokabotReconnect
}, { }, {
"trigger": "!silence", "trigger": "!silence",
"syntax": "<target> <amount> <unit(s/m/h/d)> <reason>", "syntax": "<target> <amount> <unit(s/m/h/d)> <reason>",
"minRank": 3, "privileges": privileges.ADMIN_SILENCE_USERS,
"callback": silence "callback": silence
}, { }, {
"trigger": "!removesilence", "trigger": "!removesilence",
"syntax": "<target>", "syntax": "<target>",
"minRank": 3, "privileges": privileges.ADMIN_SILENCE_USERS,
"callback": removeSilence "callback": removeSilence
}, { }, {
"trigger": "!system restart", "trigger": "!system restart",
"rank": 3, "privileges": privileges.ADMIN_MANAGE_SERVERS,
"callback": systemRestart "callback": systemRestart
}, { }, {
"trigger": "!system shutdown", "trigger": "!system shutdown",
"rank": 3, "privileges": privileges.ADMIN_MANAGE_SERVERS,
"callback": systemShutdown "callback": systemShutdown
}, { }, {
"trigger": "!system reload", "trigger": "!system reload",
"minRank": 3, "privileges": privileges.ADMIN_MANAGE_SETTINGS,
"callback": systemReload "callback": systemReload
}, { }, {
"trigger": "!system maintenance", "trigger": "!system maintenance",
"rank": 3, "privileges": privileges.ADMIN_MANAGE_SERVERS,
"callback": systemMaintenance "callback": systemMaintenance
}, { }, {
"trigger": "!system status", "trigger": "!system status",
"rank": 3, "privileges": privileges.ADMIN_MANAGE_SERVERS,
"callback": systemStatus "callback": systemStatus
}, { }, {
"trigger": "!ban", "trigger": "!ban",
"syntax": "<target>", "syntax": "<target>",
"minRank": 3, "privileges": privileges.ADMIN_BAN_USERS,
"callback": ban "callback": ban
}, { }, {
"trigger": "!unban", "trigger": "!unban",
"syntax": "<target>", "syntax": "<target>",
"minRank": 3, "privileges": privileges.ADMIN_BAN_USERS,
"callback": unban "callback": unban
}, {
"trigger": "!restrict",
"syntax": "<target>",
"privileges": privileges.ADMIN_BAN_USERS,
"callback": restrict
}, {
"trigger": "!unrestrict",
"syntax": "<target>",
"privileges": privileges.ADMIN_BAN_USERS,
"callback": unrestrict
}, { }, {
"trigger": "\x01ACTION is listening to", "trigger": "\x01ACTION is listening to",
"callback": tillerinoNp "callback": tillerinoNp
@ -684,7 +729,6 @@ commands = [
# Commands list default values # Commands list default values
for cmd in commands: for cmd in commands:
cmd.setdefault("syntax", "") cmd.setdefault("syntax", "")
cmd.setdefault("minRank", 1) cmd.setdefault("privileges", None)
cmd.setdefault("rank", None)
cmd.setdefault("callback", None) cmd.setdefault("callback", None)
cmd.setdefault("response", "u w0t m8?") cmd.setdefault("response", "u w0t m8?")

20
constants/privileges.py Normal file
View File

@ -0,0 +1,20 @@
USER_PUBLIC = 1
USER_NORMAL = 2 << 0
USER_DONOR = 2 << 1
ADMIN_ACCESS_RAP = 2 << 2
ADMIN_MANAGE_USERS = 2 << 3
ADMIN_BAN_USERS = 2 << 4
ADMIN_SILENCE_USERS = 2 << 5
ADMIN_WIPE_USERS = 2 << 6
ADMIN_MANAGE_BEATMAPS = 2 << 7
ADMIN_MANAGE_SERVERS = 2 << 8
ADMIN_MANAGE_SETTINGS = 2 << 9
ADMIN_MANAGE_BETAKEYS = 2 << 10
ADMIN_MANAGE_REPORTS = 2 << 11
ADMIN_MANAGE_DOCS = 2 << 12
ADMIN_MANAGE_BADGES = 2 << 13
ADMIN_VIEW_RAP_LOGS = 2 << 14
ADMIN_MANAGE_PRIVILEGES = 2 << 15
ADMIN_SEND_ALERTS = 2 << 16
ADMIN_CHAT_MOD = 2 << 17
ADMIN_KICK_USERS = 2 << 18

View File

@ -69,18 +69,15 @@ def friendList(userID):
return packetHelper.buildPacket(packetIDs.server_friendsList, friendsData) return packetHelper.buildPacket(packetIDs.server_friendsList, friendsData)
def onlineUsers(): def onlineUsers():
onlineUsersData = [] userIDs = []
users = glob.tokens.tokens users = glob.tokens.tokens
# Users number # Create list with all connected (and not restricted) users
onlineUsersData.append([len(users), dataTypes.uInt16]) for _, value in users.items():
if value.restricted == False:
userIDs.append(value.userID)
# Add all users user IDs to onlineUsersData return packetHelper.buildPacket(packetIDs.server_userPresenceBundle, [[userIDs, dataTypes.intList]])
for _,value in users.items():
onlineUsersData.append([value.userID, dataTypes.sInt32])
return packetHelper.buildPacket(packetIDs.server_userPresenceBundle, onlineUsersData)
""" Users packets """ """ Users packets """
@ -88,8 +85,14 @@ def userLogout(userID):
return packetHelper.buildPacket(packetIDs.server_userLogout, [[userID, dataTypes.sInt32], [0, dataTypes.byte]]) return packetHelper.buildPacket(packetIDs.server_userLogout, [[userID, dataTypes.sInt32], [0, dataTypes.byte]])
def userPanel(userID): def userPanel(userID):
# Get user data # Connected and restricted check
userToken = glob.tokens.getTokenFromUserID(userID) userToken = glob.tokens.getTokenFromUserID(userID)
if userToken == None:
return bytes()
if userToken.restricted == True:
return bytes()
# Get user data
username = userToken.username username = userToken.username
timezone = 24 # TODO: Timezone timezone = 24 # TODO: Timezone
country = userToken.country country = userToken.country
@ -99,15 +102,13 @@ def userPanel(userID):
# Get username color according to rank # Get username color according to rank
# Only admins and normal users are currently supported # Only admins and normal users are currently supported
#rank = userHelper.getRankPrivileges(userID)
rank = userToken.rank
if username == "FokaBot": if username == "FokaBot":
userRank = userRanks.MOD userRank = userRanks.MOD
elif rank == 4: elif userHelper.isInPrivilegeGroup(userID, "community manager") == True:
userRank = userRanks.MOD userRank = userRanks.MOD
elif rank == 3: elif userHelper.isInPrivilegeGroup(userID, "developer") == True:
userRank = userRanks.ADMIN userRank = userRanks.ADMIN
elif rank == 2: elif userHelper.isInPrivilegeGroup(userID, "donator") == True:
userRank = userRanks.SUPPORTER userRank = userRanks.SUPPORTER
else: else:
userRank = userRanks.NORMAL userRank = userRanks.NORMAL
@ -130,6 +131,8 @@ def userStats(userID):
userToken = glob.tokens.getTokenFromUserID(userID) userToken = glob.tokens.getTokenFromUserID(userID)
if userToken == None: if userToken == None:
return bytes() # NOTE: ??? return bytes() # NOTE: ???
if userToken.restricted == True:
return bytes()
# Stats are cached in token object # Stats are cached in token object
#rankedScore = userHelper.getRankedScore(userID, userToken.gameMode) #rankedScore = userHelper.getRankedScore(userID, userToken.gameMode)
#accuracy = userHelper.getAccuracy(userID, userToken.gameMode)/100 #accuracy = userHelper.getAccuracy(userID, userToken.gameMode)/100

View File

@ -11,10 +11,15 @@ def handle(userToken, packetData):
username = userToken.username username = userToken.username
# Make sure we are not banned # Make sure we are not banned
if userHelper.getAllowed(userID) == 0: if userHelper.isBanned(userID) == True:
userToken.enqueue(serverPackets.loginBanned()) userToken.enqueue(serverPackets.loginBanned())
return return
# Send restricted message if needed
if userToken.restricted == False:
if userHelper.isRestricted(userID) == True:
userToken.setRestricted()
# Change action packet # Change action packet
packetData = clientPackets.userActionChange(packetData) packetData = clientPackets.userActionChange(packetData)

View File

@ -26,7 +26,6 @@ def joinChannel(userToken, channelName):
# Get usertoken data # Get usertoken data
username = userToken.username username = userToken.username
userID = userToken.userID userID = userToken.userID
userRank = userToken.rank
# Check spectator channel # Check spectator channel
# If it's spectator channel, skip checks and list stuff # If it's spectator channel, skip checks and list stuff
@ -37,7 +36,7 @@ def joinChannel(userToken, channelName):
raise exceptions.channelUnknownException raise exceptions.channelUnknownException
# Check channel permissions # Check channel permissions
if glob.channels.channels[channelName].publicRead == False and userRank <= 2: if glob.channels.channels[channelName].publicRead == False and userToken.admin == False:
raise exceptions.channelNoPermissionsException raise exceptions.channelNoPermissionsException
# Add our userID to users in that channel # Add our userID to users in that channel

View File

@ -31,7 +31,8 @@ def handle(tornadoRequest):
err = False err = False
# Try to get the ID from username # Try to get the ID from username
userID = userHelper.getID(str(loginData[0])) username = str(loginData[0])
userID = userHelper.getID(username)
if userID == False: if userID == False:
# Invalid username # Invalid username
@ -41,9 +42,7 @@ def handle(tornadoRequest):
raise exceptions.loginFailedException() raise exceptions.loginFailedException()
# Make sure we are not banned # Make sure we are not banned
userAllowed = userHelper.getAllowed(userID) if userHelper.isBanned(userID) == True:
if userAllowed == 0:
# Banned
raise exceptions.loginBannedException() raise exceptions.loginBannedException()
# 2FA check # 2FA check
@ -67,10 +66,9 @@ def handle(tornadoRequest):
silenceSeconds = responseToken.getSilenceSecondsLeft() silenceSeconds = responseToken.getSilenceSecondsLeft()
# Get supporter/GMT # Get supporter/GMT
userRank = userHelper.getRankPrivileges(userID)
userGMT = False userGMT = False
userSupporter = True userSupporter = True
if userRank >= 3: if responseToken.admin == True:
userGMT = True userGMT = True
# Server restarting check # Server restarting check
@ -105,9 +103,9 @@ def handle(tornadoRequest):
# TODO: Configurable default channels # TODO: Configurable default channels
channelJoinEvent.joinChannel(responseToken, "#osu") channelJoinEvent.joinChannel(responseToken, "#osu")
channelJoinEvent.joinChannel(responseToken, "#announce") channelJoinEvent.joinChannel(responseToken, "#announce")
if userRank >= 3:
# Join admin chanenl if we are mod/admin # Join admin channel if we are an admin
# TODO: Separate channels for mods and admins if responseToken.admin == True:
channelJoinEvent.joinChannel(responseToken, "#admin") channelJoinEvent.joinChannel(responseToken, "#admin")
# Output channels info # Output channels info
@ -122,12 +120,6 @@ def handle(tornadoRequest):
if glob.banchoConf.config["menuIcon"] != "": if glob.banchoConf.config["menuIcon"] != "":
responseToken.enqueue(serverPackets.mainMenuIcon(glob.banchoConf.config["menuIcon"])) responseToken.enqueue(serverPackets.mainMenuIcon(glob.banchoConf.config["menuIcon"]))
# Get everyone else userpanel
# TODO: Better online users handling
#for key, value in glob.tokens.tokens.items():
# responseToken.enqueue(serverPackets.userPanel(value.userID))
# responseToken.enqueue(serverPackets.userStats(value.userID))
# Send online users IDs array # Send online users IDs array
responseToken.enqueue(serverPackets.onlineUsers()) responseToken.enqueue(serverPackets.onlineUsers())
@ -152,9 +144,9 @@ def handle(tornadoRequest):
if userHelper.getCountry(userID) == "XX": if userHelper.getCountry(userID) == "XX":
userHelper.setCountry(userID, countryLetters) userHelper.setCountry(userID, countryLetters)
# Send to everyone our userpanel # Send to everyone our userpanel if we are not restricted
if responseToken.restricted == False:
glob.tokens.enqueueAll(serverPackets.userPanel(userID)) glob.tokens.enqueueAll(serverPackets.userPanel(userID))
#glob.tokens.enqueueAll(serverPackets.userStats(userID))
# Set reponse data to right value and reset our queue # Set reponse data to right value and reset our queue
responseData = responseToken.queue responseData = responseToken.queue

View File

@ -24,6 +24,10 @@ def handle(userToken, packetData):
username = userToken.username username = userToken.username
userID = userToken.userID userID = userToken.userID
# Make sure the user is not in restricted mode
if userToken.restricted == True:
raise exceptions.userRestrictedException
# Private message packet # Private message packet
packetData = clientPackets.sendPrivateMessage(packetData) packetData = clientPackets.sendPrivateMessage(packetData)
@ -47,7 +51,7 @@ def handle(userToken, packetData):
raise exceptions.tokenNotFoundException() raise exceptions.tokenNotFoundException()
# Check message templates (mods/admins only) # Check message templates (mods/admins only)
if packetData["message"] in messageTemplates.templates and userToken.rank >= 3: if packetData["message"] in messageTemplates.templates and userToken.admin == True:
packetData["message"] = messageTemplates.templates[packetData["message"]] packetData["message"] = messageTemplates.templates[packetData["message"]]
# Send message to target # Send message to target
@ -71,3 +75,5 @@ def handle(userToken, packetData):
except exceptions.messageTooLongException: except exceptions.messageTooLongException:
# Message > 256 silence # Message > 256 silence
userToken.silence(2*3600, "Sending messages longer than 256 characters") userToken.silence(2*3600, "Sending messages longer than 256 characters")
except exceptions.userRestrictedException:
pass

View File

@ -20,7 +20,10 @@ def handle(userToken, packetData):
# Get userToken data # Get userToken data
userID = userToken.userID userID = userToken.userID
username = userToken.username username = userToken.username
userRank = userToken.rank
# Make sure the user is not in restricted mode
if userToken.restricted == True:
raise exceptions.userRestrictedException
# Public chat packet # Public chat packet
packetData = clientPackets.sendPublicMessage(packetData) packetData = clientPackets.sendPublicMessage(packetData)
@ -85,11 +88,11 @@ def handle(userToken, packetData):
raise exceptions.channelUnknownException raise exceptions.channelUnknownException
# Make sure the channel is not in moderated mode # Make sure the channel is not in moderated mode
if glob.channels.channels[packetData["to"]].moderated == True and userRank <= 2: if glob.channels.channels[packetData["to"]].moderated == True and userToken.admin == False:
raise exceptions.channelModeratedException raise exceptions.channelModeratedException
# Make sure we have write permissions # Make sure we have write permissions
if glob.channels.channels[packetData["to"]].publicWrite == False and userRank <= 2: if glob.channels.channels[packetData["to"]].publicWrite == False and userToken.admin == False:
raise exceptions.channelNoPermissionsException raise exceptions.channelNoPermissionsException
# Send this packet to everyone in that channel except us # Send this packet to everyone in that channel except us
@ -128,3 +131,5 @@ def handle(userToken, packetData):
except exceptions.messageTooLongException: except exceptions.messageTooLongException:
# Message > 256 silence # Message > 256 silence
userToken.silence(2*3600, "Sending messages longer than 256 characters") userToken.silence(2*3600, "Sending messages longer than 256 characters")
except exceptions.userRestrictedException:
pass

View File

@ -156,9 +156,25 @@ class handler(SentryMixin, requestHelper.asyncRequestHandler):
packetIDs.client_userPanelRequest: handleEvent(userPanelRequestEvent), packetIDs.client_userPanelRequest: handleEvent(userPanelRequestEvent),
} }
# Packets processed if in restricted mode.
# All other packets will be ignored if the user is in restricted mode
packetsRestricted = [
packetIDs.client_logout,
packetIDs.client_userStatsRequest,
packetIDs.client_requestStatusUpdate,
packetIDs.client_userPanelRequest,
packetIDs.client_changeAction,
packetIDs.client_channelJoin,
packetIDs.client_channelPart,
]
# Process/ignore packet
if packetID != 4: if packetID != 4:
if packetID in eventHandler: if packetID in eventHandler:
if userToken.restricted == False or (userToken.restricted == True and packetID in packetsRestricted):
eventHandler[packetID]() eventHandler[packetID]()
else:
log.warning("Ignored packet id from {} ({}) (user is restricted)".format(requestTokenString, packetID))
else: else:
log.warning("Unknown packet id from {} ({})".format(requestTokenString, packetID)) log.warning("Unknown packet id from {} ({})".format(requestTokenString, packetID))

View File

@ -4,7 +4,7 @@ import json
from helpers import logHelper as log from helpers import logHelper as log
# API URL # API URL
URL = "http://ip.zxq.co/" URL = "http://ipinfo.io/"
def getCountry(ip): def getCountry(ip):

View File

@ -100,6 +100,14 @@ def packData(__data, __dataType):
# Bytes, do not use pack, do manually # Bytes, do not use pack, do manually
pack = False pack = False
data = __data data = __data
elif __dataType == dataTypes.intList:
# Pack manually
pack = False
# Add length
data = packData(len(__data), dataTypes.uInt16)
# Add all elements
for i in __data:
data += packData(i, dataTypes.sInt32)
elif __dataType == dataTypes.string: elif __dataType == dataTypes.string:
# String, do not use pack, do manually # String, do not use pack, do manually
pack = False pack = False

View File

@ -4,6 +4,7 @@ from helpers import generalFunctions
from objects import glob from objects import glob
from helpers import logHelper as log from helpers import logHelper as log
import time import time
from constants import privileges
def getID(username): def getID(username):
""" """
@ -67,27 +68,6 @@ def exists(userID):
else: else:
return True return True
def getAllowed(userID):
"""
Get allowed status for userID
db -- database connection
userID -- user ID
return -- allowed int
"""
return glob.db.fetch("SELECT allowed FROM users WHERE id = %s", [userID])["allowed"]
def getRankPrivileges(userID):
"""
This returns rank **(PRIVILEGES)**, not game rank (like #1337)
If you want to get that rank, user getUserGameRank instead
"""
return glob.db.fetch("SELECT rank FROM users WHERE id = %s", [userID])["rank"]
def getSilenceEnd(userID): def getSilenceEnd(userID):
""" """
Get userID's **ABSOLUTE** silence end UNIX time Get userID's **ABSOLUTE** silence end UNIX time
@ -279,16 +259,6 @@ def getPP(userID, gameMode):
modeForDB = gameModes.getGameModeForDB(gameMode) modeForDB = gameModes.getGameModeForDB(gameMode)
return glob.db.fetch("SELECT pp_{} FROM users_stats WHERE id = %s".format(modeForDB), [userID])["pp_{}".format(modeForDB)] return glob.db.fetch("SELECT pp_{} FROM users_stats WHERE id = %s".format(modeForDB), [userID])["pp_{}".format(modeForDB)]
def setAllowed(userID, allowed):
"""
Set userID's allowed status
userID -- user
allowed -- allowed status. 1: normal, 0: banned
"""
banDateTime = int(time.time()) if allowed == 0 else 0
glob.db.execute("UPDATE users SET allowed = %s, ban_datetime = %s WHERE id = %s", [allowed, banDateTime, userID])
def setCountry(userID, country): def setCountry(userID, country):
""" """
Set userID's country (two letters) Set userID's country (two letters)
@ -375,3 +345,102 @@ def getUserStats(userID, gameMode):
# Return stats + game rank # Return stats + game rank
return stats return stats
def isAllowed(userID):
"""
Check if userID is not banned or restricted
userID -- id of the user
return -- True if not banned or restricted, otherwise false.
"""
result = glob.db.fetch("SELECT privileges FROM users WHERE id = %s", [userID])
if result != None:
return (result["privileges"] & privileges.USER_NORMAL) and (result["privileges"] & privileges.USER_PUBLIC)
else:
return False
def isRestricted(userID):
"""
Check if userID is restricted
userID -- id of the user
return -- True if not restricted, otherwise false.
"""
result = glob.db.fetch("SELECT privileges FROM users WHERE id = %s", [userID])
if result != None:
return (result["privileges"] & privileges.USER_NORMAL) and not (result["privileges"] & privileges.USER_PUBLIC)
else:
return False
def isBanned(userID):
"""
Check if userID is banned
userID -- id of the user
return -- True if not banned, otherwise false.
"""
result = glob.db.fetch("SELECT privileges FROM users WHERE id = %s", [userID])
if result != None:
return not (result["privileges"] & privileges.USER_NORMAL) and not (result["privileges"] & privileges.USER_PUBLIC)
else:
return True
def ban(userID):
"""
Ban userID
userID -- id of user
"""
banDateTime = int(time.time())
glob.db.execute("UPDATE users SET privileges = privileges & %s, ban_datetime = %s WHERE id = %s", [ ~(privileges.USER_NORMAL | privileges.USER_PUBLIC) , banDateTime, userID])
def unban(userID):
"""
Unban userID
userID -- id of user
"""
glob.db.execute("UPDATE users SET privileges = privileges | %s, ban_datetime = 0 WHERE id = %s", [ (privileges.USER_NORMAL | privileges.USER_PUBLIC) , userID])
def restrict(userID):
"""
Put userID in restricted mode
userID -- id of user
"""
banDateTime = int(time.time())
glob.db.execute("UPDATE users SET privileges = privileges & %s, ban_datetime = %s WHERE id = %s", [~privileges.USER_PUBLIC, banDateTime, userID])
def unrestrict(userID):
"""
Remove restricted mode from userID.
Same as unban().
userID -- id of user
"""
unban(userID)
def getPrivileges(userID):
"""
Return privileges for userID
userID -- id of user
return -- privileges number
"""
result = glob.db.fetch("SELECT privileges FROM users WHERE id = %s", [userID])
if result != None:
return result["privileges"]
else:
return 0
def isInPrivilegeGroup(userID, groupName):
groupPrivileges = glob.db.fetch("SELECT privileges FROM privileges_groups WHERE name = %s", [groupName])
if groupPrivileges == None:
return False
groupPrivileges = groupPrivileges["privileges"]
userToken = glob.tokens.getTokenFromUserID(userID)
if userToken != None:
userPrivileges = userToken.privileges
else:
userPrivileges = getPrivileges(userID)
return (userPrivileges == groupPrivileges) or (userPrivileges == (groupPrivileges | privileges.USER_DONOR))

View File

@ -47,15 +47,9 @@ def fokabotResponse(fro, chan, message):
# message has triggered a command # message has triggered a command
# Make sure the user has right permissions # Make sure the user has right permissions
if i["rank"] != None: if i["privileges"] != None:
# Rank = x # Rank = x
if userHelper.getRankPrivileges(userHelper.getID(fro)) != i["rank"]: if userHelper.getPrivileges(userHelper.getID(fro)) & i["privileges"] == 0:
return False
else:
# Rank > x
if i["minRank"] > 1:
# Get rank from db only if minrank > 1, so we save some CPU
if userHelper.getRankPrivileges(userHelper.getID(fro)) < i["minRank"]:
return False return False
# Check argument number # Check argument number

View File

@ -8,6 +8,7 @@ from objects import glob
import uuid import uuid
import time import time
import threading import threading
from helpers import logHelper as log
class token: class token:
""" """
@ -16,7 +17,6 @@ class token:
token -- token string token -- token string
userID -- userID associated to that token userID -- userID associated to that token
username -- username relative to userID (cache) username -- username relative to userID (cache)
rank -- rank (permissions) relative to userID (cache)
actionID -- current user action (see actions.py) actionID -- current user action (see actions.py)
actionText -- current user action text actionText -- current user action text
actionMd5 -- md5 relative to user action actionMd5 -- md5 relative to user action
@ -47,7 +47,11 @@ class token:
# Set stuff # Set stuff
self.userID = __userID self.userID = __userID
self.username = userHelper.getUsername(self.userID) self.username = userHelper.getUsername(self.userID)
self.rank = userHelper.getRankPrivileges(self.userID) self.privileges = userHelper.getPrivileges(self.userID)
self.admin = userHelper.isInPrivilegeGroup(self.userID, "developer") or userHelper.isInPrivilegeGroup(self.userID, "community manager")
self.restricted = userHelper.isRestricted(self.userID)
if self.restricted == True:
self.setRestricted()
self.loginTime = int(time.time()) self.loginTime = int(time.time())
self.pingTime = self.loginTime self.pingTime = self.loginTime
self.lock = threading.Lock() # Sync primitive self.lock = threading.Lock() # Sync primitive
@ -69,7 +73,6 @@ class token:
# Spam protection # Spam protection
self.spamRate = 0 self.spamRate = 0
#self.lastMessagetime = 0
# Stats cache # Stats cache
self.actionID = actions.idle self.actionID = actions.idle
@ -295,3 +298,11 @@ class token:
self.totalScore = stats["totalScore"] self.totalScore = stats["totalScore"]
self.gameRank = stats["gameRank"] self.gameRank = stats["gameRank"]
self.pp = stats["pp"] self.pp = stats["pp"]
def setRestricted(self):
"""
Set this token as restricted, send FokaBot message to user
and send offline packet to everyone
"""
self.restricted = True
self.enqueue(serverPackets.sendMessage("FokaBot", self.username, "Your account is currently in restricted mode. Please visit ripple's website for more information."))

View File

@ -1 +1 @@
1.3.3 1.3.