621 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			621 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from helpers import passwordHelper
 | |
| from constants import gameModes
 | |
| from helpers import generalFunctions
 | |
| from objects import glob
 | |
| from helpers import logHelper as log
 | |
| import time
 | |
| from constants import privileges
 | |
| 
 | |
| def getID(username):
 | |
| 	"""
 | |
| 	Get username's user ID
 | |
| 
 | |
| 	db -- database connection
 | |
| 	username -- user
 | |
| 	return -- user id or False
 | |
| 	"""
 | |
| 
 | |
| 	# Get user ID from db
 | |
| 	userID = glob.db.fetch("SELECT id FROM users WHERE username = %s", [username])
 | |
| 
 | |
| 	# Make sure the query returned something
 | |
| 	if userID == None:
 | |
| 		return False
 | |
| 
 | |
| 	# Return user ID
 | |
| 	return userID["id"]
 | |
| 
 | |
| 
 | |
| def checkLogin(userID, password):
 | |
| 	"""
 | |
| 	Check userID's login with specified password
 | |
| 
 | |
| 	db -- database connection
 | |
| 	userID -- user id
 | |
| 	password -- plain md5 password
 | |
| 	return -- True or False
 | |
| 	"""
 | |
| 
 | |
| 	# Get password data
 | |
| 	passwordData = glob.db.fetch("SELECT password_md5, salt, password_version FROM users WHERE id = %s", [userID])
 | |
| 
 | |
| 	# Make sure the query returned something
 | |
| 	if passwordData == None:
 | |
| 		return False
 | |
| 
 | |
| 
 | |
| 	# Return valid/invalid based on the password version.
 | |
| 	if passwordData["password_version"] == 2:
 | |
| 		return passwordHelper.checkNewPassword(password, passwordData["password_md5"])
 | |
| 	if passwordData["password_version"] == 1:
 | |
| 		ok = passwordHelper.checkOldPassword(password, passwordData["salt"], passwordData["password_md5"])
 | |
| 		if not ok: return False
 | |
| 		newpass = passwordHelper.genBcrypt(password)
 | |
| 		glob.db.execute("UPDATE users SET password_md5=%s, salt='', password_version='2' WHERE id = %s", [newpass, userID])
 | |
| 
 | |
| 
 | |
| def exists(userID):
 | |
| 	"""
 | |
| 	Check if userID exists
 | |
| 
 | |
| 	userID -- user ID to check
 | |
| 	return -- bool
 | |
| 	"""
 | |
| 
 | |
| 	result = glob.db.fetch("SELECT id FROM users WHERE id = %s", [userID])
 | |
| 	if result == None:
 | |
| 		return False
 | |
| 	else:
 | |
| 		return True
 | |
| 
 | |
| def getSilenceEnd(userID):
 | |
| 	"""
 | |
| 	Get userID's **ABSOLUTE** silence end UNIX time
 | |
| 	Remember to subtract time.time() to get the actual silence time
 | |
| 
 | |
| 	userID -- userID
 | |
| 	return -- UNIX time
 | |
| 	"""
 | |
| 
 | |
| 	return glob.db.fetch("SELECT silence_end FROM users WHERE id = %s", [userID])["silence_end"]
 | |
| 
 | |
| 
 | |
| def silence(userID, seconds, silenceReason, author = 999):
 | |
| 	"""
 | |
| 	Silence someone
 | |
| 
 | |
| 	userID -- userID
 | |
| 	seconds -- silence length in seconds
 | |
| 	silenceReason -- Silence reason shown on website
 | |
| 	author -- userID of who silenced the user. Default: 999
 | |
| 	"""
 | |
| 	# db qurey
 | |
| 	silenceEndTime = int(time.time())+seconds
 | |
| 	glob.db.execute("UPDATE users SET silence_end = %s, silence_reason = %s WHERE id = %s", [silenceEndTime, silenceReason, userID])
 | |
| 
 | |
| 	# Loh
 | |
| 	targetUsername = getUsername(userID)
 | |
| 	# TODO: exists check im drunk rn i need to sleep (stampa piede ubriaco confirmed)
 | |
| 	if seconds > 0:
 | |
| 		log.rap(author, "has silenced {} for {} seconds for the following reason: \"{}\"".format(targetUsername, seconds, silenceReason), True)
 | |
| 	else:
 | |
| 		log.rap(author, "has removed {}'s silence".format(targetUsername), True)
 | |
| 
 | |
| def getRankedScore(userID, gameMode):
 | |
| 	"""
 | |
| 	Get userID's ranked score relative to gameMode
 | |
| 
 | |
| 	userID -- userID
 | |
| 	gameMode -- int value, see gameModes
 | |
| 	return -- ranked score
 | |
| 	"""
 | |
| 
 | |
| 	modeForDB = gameModes.getGameModeForDB(gameMode)
 | |
| 	return glob.db.fetch("SELECT ranked_score_"+modeForDB+" FROM users_stats WHERE id = %s", [userID])["ranked_score_"+modeForDB]
 | |
| 
 | |
| 
 | |
| def getTotalScore(userID, gameMode):
 | |
| 	"""
 | |
| 	Get userID's total score relative to gameMode
 | |
| 
 | |
| 	userID -- userID
 | |
| 	gameMode -- int value, see gameModes
 | |
| 	return -- total score
 | |
| 	"""
 | |
| 
 | |
| 	modeForDB = gameModes.getGameModeForDB(gameMode)
 | |
| 	return glob.db.fetch("SELECT total_score_"+modeForDB+" FROM users_stats WHERE id = %s", [userID])["total_score_"+modeForDB]
 | |
| 
 | |
| 
 | |
| def getAccuracy(userID, gameMode):
 | |
| 	"""
 | |
| 	Get userID's average accuracy relative to gameMode
 | |
| 
 | |
| 	userID -- userID
 | |
| 	gameMode -- int value, see gameModes
 | |
| 	return -- accuracy
 | |
| 	"""
 | |
| 
 | |
| 	modeForDB = gameModes.getGameModeForDB(gameMode)
 | |
| 	return glob.db.fetch("SELECT avg_accuracy_"+modeForDB+" FROM users_stats WHERE id = %s", [userID])["avg_accuracy_"+modeForDB]
 | |
| 
 | |
| 
 | |
| def getGameRank(userID, gameMode):
 | |
| 	"""
 | |
| 	Get userID's **in-game rank** (eg: #1337) relative to gameMode
 | |
| 
 | |
| 	userID -- userID
 | |
| 	gameMode -- int value, see gameModes
 | |
| 	return -- game rank
 | |
| 	"""
 | |
| 
 | |
| 	modeForDB = gameModes.getGameModeForDB(gameMode)
 | |
| 	result = glob.db.fetch("SELECT position FROM leaderboard_"+modeForDB+" WHERE user = %s", [userID])
 | |
| 	if result == None:
 | |
| 		return 0
 | |
| 	else:
 | |
| 		return result["position"]
 | |
| 
 | |
| 
 | |
| def getPlaycount(userID, gameMode):
 | |
| 	"""
 | |
| 	Get userID's playcount relative to gameMode
 | |
| 
 | |
| 	userID -- userID
 | |
| 	gameMode -- int value, see gameModes
 | |
| 	return -- playcount
 | |
| 	"""
 | |
| 
 | |
| 	modeForDB = gameModes.getGameModeForDB(gameMode)
 | |
| 	return glob.db.fetch("SELECT playcount_"+modeForDB+" FROM users_stats WHERE id = %s", [userID])["playcount_"+modeForDB]
 | |
| 
 | |
| 
 | |
| def getUsername(userID):
 | |
| 	"""
 | |
| 	Get userID's username
 | |
| 
 | |
| 	userID -- userID
 | |
| 	return -- username
 | |
| 	"""
 | |
| 
 | |
| 	return glob.db.fetch("SELECT username FROM users WHERE id = %s", [userID])["username"]
 | |
| 
 | |
| 
 | |
| def getFriendList(userID):
 | |
| 	"""
 | |
| 	Get userID's friendlist
 | |
| 
 | |
| 	userID -- userID
 | |
| 	return -- list with friends userIDs. [0] if no friends.
 | |
| 	"""
 | |
| 
 | |
| 	# Get friends from db
 | |
| 	friends = glob.db.fetchAll("SELECT user2 FROM users_relationships WHERE user1 = %s", [userID])
 | |
| 
 | |
| 	if friends == None or len(friends) == 0:
 | |
| 		# We have no friends, return 0 list
 | |
| 		return [0]
 | |
| 	else:
 | |
| 		# Get only friends
 | |
| 		friends = [i["user2"] for i in friends]
 | |
| 
 | |
| 		# Return friend IDs
 | |
| 		return friends
 | |
| 
 | |
| 
 | |
| def addFriend(userID, friendID):
 | |
| 	"""
 | |
| 	Add friendID to userID's friend list
 | |
| 
 | |
| 	userID -- user
 | |
| 	friendID -- new friend
 | |
| 	"""
 | |
| 
 | |
| 	# Make sure we aren't adding us to our friends
 | |
| 	if userID == friendID:
 | |
| 		return
 | |
| 
 | |
| 	# check user isn't already a friend of ours
 | |
| 	if glob.db.fetch("SELECT id FROM users_relationships WHERE user1 = %s AND user2 = %s", [userID, friendID]) != None:
 | |
| 		return
 | |
| 
 | |
| 	# Set new value
 | |
| 	glob.db.execute("INSERT INTO users_relationships (user1, user2) VALUES (%s, %s)", [userID, friendID])
 | |
| 
 | |
| 
 | |
| def removeFriend(userID, friendID):
 | |
| 	"""
 | |
| 	Remove friendID from userID's friend list
 | |
| 
 | |
| 	userID -- user
 | |
| 	friendID -- old friend
 | |
| 	"""
 | |
| 
 | |
| 	# Delete user relationship. We don't need to check if the relationship was there, because who gives a shit,
 | |
| 	# if they were not friends and they don't want to be anymore, be it. ¯\_(ツ)_/¯
 | |
| 	glob.db.execute("DELETE FROM users_relationships WHERE user1 = %s AND user2 = %s", [userID, friendID])
 | |
| 
 | |
| 
 | |
| def getCountry(userID):
 | |
| 	"""
 | |
| 	Get userID's country **(two letters)**.
 | |
| 	Use countryHelper.getCountryID with what that function returns
 | |
| 	to get osu! country ID relative to that user
 | |
| 
 | |
| 	userID -- user
 | |
| 	return -- country code (two letters)
 | |
| 	"""
 | |
| 
 | |
| 	return glob.db.fetch("SELECT country FROM users_stats WHERE id = %s", [userID])["country"]
 | |
| 
 | |
| def getPP(userID, gameMode):
 | |
| 	"""
 | |
| 	Get userID's PP relative to gameMode
 | |
| 
 | |
| 	userID -- user
 | |
| 	return -- PP
 | |
| 	"""
 | |
| 
 | |
| 	modeForDB = gameModes.getGameModeForDB(gameMode)
 | |
| 	return glob.db.fetch("SELECT pp_{} FROM users_stats WHERE id = %s".format(modeForDB), [userID])["pp_{}".format(modeForDB)]
 | |
| 
 | |
| def setCountry(userID, country):
 | |
| 	"""
 | |
| 	Set userID's country (two letters)
 | |
| 
 | |
| 	userID -- userID
 | |
| 	country -- country letters
 | |
| 	"""
 | |
| 	glob.db.execute("UPDATE users_stats SET country = %s WHERE id = %s", [country, userID])
 | |
| 
 | |
| def getShowCountry(userID):
 | |
| 	"""
 | |
| 	Get userID's show country status
 | |
| 
 | |
| 	userID -- userID
 | |
| 	return -- True if country is shown, False if it's hidden
 | |
| 	"""
 | |
| 	country = glob.db.fetch("SELECT show_country FROM users_stats WHERE id = %s", [userID])
 | |
| 	if country == None:
 | |
| 		return False
 | |
| 	return generalFunctions.stringToBool(country)
 | |
| 
 | |
| def IPLog(userID, ip):
 | |
| 	"""
 | |
| 	Botnet the user
 | |
| 	(log his ip for multiaccount detection)
 | |
| 	"""
 | |
| 	glob.db.execute("""INSERT INTO ip_user (userid, ip, occurencies) VALUES (%s, %s, '1')
 | |
| 						ON DUPLICATE KEY UPDATE occurencies = occurencies + 1""", [userID, ip])
 | |
| 
 | |
| def saveBanchoSession(userID, ip):
 | |
| 	"""
 | |
| 	Save userid and ip of this token in bancho_sessions table.
 | |
| 	Used to cache logins on LETS requests
 | |
| 	"""
 | |
| 	log.debug("Saving bancho session ({}::{}) in db".format(userID, ip))
 | |
| 	glob.db.execute("INSERT INTO bancho_sessions (id, userid, ip) VALUES (NULL, %s, %s)", [userID, ip])
 | |
| 
 | |
| def deleteBanchoSessions(userID, ip):
 | |
| 	"""Delete this bancho session from DB"""
 | |
| 	log.debug("Deleting bancho session ({}::{}) from db".format(userID, ip))
 | |
| 	try:
 | |
| 		glob.db.execute("DELETE FROM bancho_sessions WHERE userid = %s AND ip = %s", [userID, ip])
 | |
| 	except:
 | |
| 		log.warning("Token for user: {} ip: {} doesn't exist".format(userID, ip))
 | |
| 
 | |
| def is2FAEnabled(userID):
 | |
| 	"""Returns True if 2FA is enable for this account"""
 | |
| 	result = glob.db.fetch("SELECT id FROM 2fa_telegram WHERE userid = %s LIMIT 1", [userID])
 | |
| 	return True if result is not None else False
 | |
| 
 | |
| def check2FA(userID, ip):
 | |
| 	"""Returns True if this IP is untrusted"""
 | |
| 	if is2FAEnabled(userID) == False:
 | |
| 		return False
 | |
| 
 | |
| 	result = glob.db.fetch("SELECT id FROM ip_user WHERE userid = %s AND ip = %s", [userID, ip])
 | |
| 	return True if result is None else False
 | |
| 
 | |
| def getUserStats(userID, gameMode):
 | |
| 	"""
 | |
| 	Get all user stats relative to gameMode with only two queries
 | |
| 
 | |
| 	userID --
 | |
| 	gameMode -- gameMode number
 | |
| 	return -- dictionary with results
 | |
| 	"""
 | |
| 	modeForDB = gameModes.getGameModeForDB(gameMode)
 | |
| 
 | |
| 	# Get stats
 | |
| 	stats = glob.db.fetch("""SELECT
 | |
| 						ranked_score_{gm} AS rankedScore,
 | |
| 						avg_accuracy_{gm} AS accuracy,
 | |
| 						playcount_{gm} AS playcount,
 | |
| 						total_score_{gm} AS totalScore,
 | |
| 						pp_{gm} AS pp
 | |
| 						FROM users_stats WHERE id = %s LIMIT 1""".format(gm=modeForDB), [userID])
 | |
| 
 | |
| 	# Get game rank
 | |
| 	result = glob.db.fetch("SELECT position FROM leaderboard_{} WHERE user = %s LIMIT 1".format(modeForDB), [userID])
 | |
| 	if result == None:
 | |
| 		stats["gameRank"] = 0
 | |
| 	else:
 | |
| 		stats["gameRank"] = result["position"]
 | |
| 
 | |
| 	# Return stats + game rank
 | |
| 	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"] & 3 > 0)
 | |
| 	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 | privileges.USER_PENDING_VERIFICATION) , 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 setPrivileges(userID, priv):
 | |
| 	"""
 | |
| 	Set userID's privileges in db
 | |
| 
 | |
| 	userID -- id of user
 | |
| 	priv -- privileges number
 | |
| 	"""
 | |
| 	glob.db.execute("UPDATE users SET privileges = %s WHERE id = %s", [priv, userID])
 | |
| 
 | |
| 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))
 | |
| 
 | |
| 
 | |
| def appendNotes(userID, notes, addNl = True):
 | |
| 	"""
 | |
| 	Append "notes" to current userID's "notes for CM"
 | |
| 
 | |
| 	userID -- id of user
 | |
| 	notes -- text to append
 | |
| 	addNl -- if True, prepend \n to notes. Optional. Default: True.
 | |
| 	"""
 | |
| 	if addNl == True:
 | |
| 		notes = "\n"+notes
 | |
| 	glob.db.execute("UPDATE users SET notes=CONCAT(COALESCE(notes, ''),%s) WHERE id = %s", [notes, userID])
 | |
| 
 | |
| 
 | |
| def logHardware(userID, hashes, activation = False):
 | |
| 	"""
 | |
| 	Hardware log
 | |
| 
 | |
| 	Peppy's botnet structure (new line = "|", already split)
 | |
| 	[0] osu! version
 | |
| 	[1] plain mac addressed, separated by "."
 | |
| 	[2] mac addresses hash set
 | |
| 	[3] unique ID
 | |
| 	[4] disk ID
 | |
| 
 | |
| 	return -- True if hw is not banned, otherwise false
 | |
| 	"""
 | |
| 	# Make sure the strings are not empty
 | |
| 	for i in hashes[2:5]:
 | |
| 		if i == "":
 | |
| 			log.warning("Invalid hash set ({}) for user {} in HWID check".format(hashes, userID), "bunk")
 | |
| 			return False
 | |
| 
 | |
| 	# Run some HWID checks on that user if he is not restricted
 | |
| 	if isRestricted(userID) == False:
 | |
| 		# Get username
 | |
| 		username = getUsername(userID)
 | |
| 
 | |
| 		# Get the list of banned or restricted users that have logged in from this or similar HWID hash set
 | |
| 		banned = glob.db.fetchAll("""SELECT users.id as userid, hw_user.occurencies, users.username FROM hw_user
 | |
| 						LEFT JOIN users ON users.id = hw_user.userid
 | |
| 						WHERE hw_user.userid != %(userid)s
 | |
| 						AND (IF(%(mac)s!='b4ec3c4334a0249dae95c284ec5983df', hw_user.mac = %(mac)s, 0) OR hw_user.unique_id = %(uid)s OR hw_user.disk_id = %(diskid)s)
 | |
| 						AND (users.privileges & 3 != 3)""", {
 | |
| 							"userid": userID,
 | |
| 							"mac": hashes[2],
 | |
| 							"uid": hashes[3],
 | |
| 							"diskid": hashes[4],
 | |
| 						})
 | |
| 
 | |
| 		for i in banned:
 | |
| 			# Get the total numbers of logins
 | |
| 			total = glob.db.fetch("SELECT COUNT(*) AS count FROM hw_user WHERE userid = %s LIMIT 1", [userID])
 | |
| 			# and make sure it is valid
 | |
| 			if total == None:
 | |
| 				continue
 | |
| 			total = total["count"]
 | |
| 
 | |
| 			# Calculate 10% of total
 | |
| 			perc = (total*10)/100
 | |
| 
 | |
| 			if i["occurencies"] >= perc:
 | |
| 				# If the banned user has logged in more than 10% of the times from this user, restrict this user
 | |
| 				restrict(userID)
 | |
| 				appendNotes(userID, "-- Logged in from HWID ({hwid}) used more than 10% from user {banned} ({bannedUserID}), who is banned/restricted.".format(
 | |
| 					hwid=hashes[2:5],
 | |
| 					banned=i["username"],
 | |
| 					bannedUserID=i["userid"]
 | |
| 				))
 | |
| 				log.warning("**{user}** ({userID}) has been restricted because he has logged in from HWID _({hwid})_ used more than 10% from banned/restricted user **{banned}** ({bannedUserID}), **possible multiaccount**.".format(
 | |
| 					user=username,
 | |
| 					userID=userID,
 | |
| 					hwid=hashes[2:5],
 | |
| 					banned=i["username"],
 | |
| 					bannedUserID=i["userid"]
 | |
| 				), "cm")
 | |
| 
 | |
| 	# Update hash set occurencies
 | |
| 	glob.db.execute("""
 | |
| 				INSERT INTO hw_user (id, userid, mac, unique_id, disk_id, occurencies) VALUES (NULL, %s, %s, %s, %s, 1)
 | |
| 				ON DUPLICATE KEY UPDATE occurencies = occurencies + 1
 | |
| 				""", [userID, hashes[2], hashes[3], hashes[4]])
 | |
| 
 | |
| 	# Optionally, set this hash as 'used for activation'
 | |
| 	if activation == True:
 | |
| 		glob.db.execute("UPDATE hw_user SET activated = 1 WHERE userid = %s AND mac = %s AND unique_id = %s AND disk_id = %s", [userID, hashes[2], hashes[3], hashes[4]])
 | |
| 
 | |
| 	# Access granted, abbiamo impiegato 3 giorni
 | |
| 	# We grant access even in case of login from banned HWID
 | |
| 	# because we call restrict() above so there's no need to deny the access.
 | |
| 	return True
 | |
| 
 | |
| 
 | |
| def resetPendingFlag(userID, success=True):
 | |
| 	"""
 | |
| 	Remove pending flag from an user.
 | |
| 
 | |
| 	userID -- ID of the user
 | |
| 	success -- if True, set USER_PUBLIC and USER_NORMAL flags too
 | |
| 	"""
 | |
| 	glob.db.execute("UPDATE users SET privileges = privileges & %s WHERE id = %s LIMIT 1", [~privileges.USER_PENDING_VERIFICATION, userID])
 | |
| 	if success == True:
 | |
| 		glob.db.execute("UPDATE users SET privileges = privileges | %s WHERE id = %s LIMIT 1", [(privileges.USER_PUBLIC | privileges.USER_NORMAL), userID])
 | |
| 
 | |
| def verifyUser(userID, hashes):
 | |
| 	# Check for valid hash set
 | |
| 	for i in hashes[2:5]:
 | |
| 		if i == "":
 | |
| 			log.warning("Invalid hash set ({}) for user {} while verifying the account".format(str(hashes), userID), "bunk")
 | |
| 			return False
 | |
| 
 | |
| 	# Get username
 | |
| 	username = getUsername(userID)
 | |
| 
 | |
| 	# Make sure there are no other accounts activated with this exact mac/unique id/hwid
 | |
| 	match = glob.db.fetchAll("SELECT userid FROM hw_user WHERE (IF(%(mac)s != 'b4ec3c4334a0249dae95c284ec5983df', mac = %(mac)s, 0) OR unique_id = %(uid)s OR disk_id = %(diskid)s) AND userid != %(userid)s AND activated = 1 LIMIT 1", {
 | |
| 		"mac": hashes[2],
 | |
| 		"uid": hashes[3],
 | |
| 		"diskid": hashes[4],
 | |
| 		"userid": userID
 | |
| 	})
 | |
| 
 | |
| 	if match:
 | |
| 		# This is a multiaccount, restrict other account and ban this account
 | |
| 
 | |
| 		# Get original userID and username (lowest ID)
 | |
| 		originalUserID = match[0]["userid"]
 | |
| 		originalUsername = getUsername(originalUserID)
 | |
| 
 | |
| 		# Ban this user and append notes
 | |
| 		ban(userID)	# this removes the USER_PENDING_VERIFICATION flag too
 | |
| 		appendNotes(userID, "-- {}'s multiaccount ({}), found HWID match while verifying account ({})".format(originalUsername, originalUserID, hashes[2:5]))
 | |
| 		appendNotes(originalUserID, "-- Has created multiaccount {} ({})".format(username, userID))
 | |
| 
 | |
| 		# Restrict the original
 | |
| 		restrict(originalUserID)
 | |
| 
 | |
| 		# Discord message
 | |
| 		log.warning("User **{originalUsername}** ({originalUserID}) has been restricted because he has created multiaccount **{username}** ({userID}). The multiaccount has been banned.".format(
 | |
| 			originalUsername=originalUsername,
 | |
| 			originalUserID=originalUserID,
 | |
| 			username=username,
 | |
| 			userID=userID
 | |
| 		), "cm")
 | |
| 
 | |
| 		# Disallow login
 | |
| 		return False
 | |
| 	else:
 | |
| 		# No matches found, set USER_PUBLIC and USER_NORMAL flags and reset USER_PENDING_VERIFICATION flag
 | |
| 		resetPendingFlag(userID)
 | |
| 		log.info("User **{}** ({}) has verified his account with hash set _{}_".format(username, userID, hashes[2:5]), "cm")
 | |
| 
 | |
| 		# Allow login
 | |
| 		return True
 | |
| 
 | |
| def hasVerifiedHardware(userID):
 | |
| 	"""
 | |
| 	userID -- id of the user
 | |
| 	return -- True if hwid activation data is in db, otherwise false
 | |
| 	"""
 | |
| 	data = glob.db.fetch("SELECT id FROM hw_user WHERE userid = %s AND activated = 1 LIMIT 1", [userID])
 | |
| 	if data != None:
 | |
| 		return True
 | |
| 	return False
 |