def _confirm_password(caller, user_input): password = caller.ndb.new_password menutree = caller.ndb._menutree if user_input == password: # Create the new player account playername = menutree.playername from evennia.commands.default import unloggedin # We make use of the helper functions from the default set here. # noinspection PyBroadException try: permissions = settings.PERMISSION_PLAYER_DEFAULT new_player = unloggedin._create_player(caller, playername, password, permissions) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, we # won't see any errors at all. caller.msg(LOGIN_ERROR) logger.log_trace() else: caller.ndb.passed_account_creation = True caller.msg(LOGIN_ACCOUNT_CREATED.format(playername)) caller.sessionhandler.login(caller, new_player) else: caller.msg(LOGIN_PASSWORD_MISMATCH) caller.ndb.confirm_needed = False
def create_password(caller, string_input): """Ask the user to create a password. This node is at the end of the menu for account creation. If a proper MULTI_SESSION is configured, a character is also created with the same name (we try to login into it). """ menutree = caller.ndb._menutree text = "" options = ( {"key": "", "exec": lambda caller: caller.msg("", options={"echo": True}), "goto": "start"}, {"key": "_default", "goto": "create_password"}) password = string_input.strip() playername = menutree.playername if len(password) < LEN_PASSWD: # The password is too short text = dedent(""" |rYour password must be at least {} characters long.|n Enter another password or leave it empty to go back. """.strip("\n")).format(LEN_PASSWD) else: # Everything's OK. Create the new player account and # possibly the character, depending on the multisession mode from evennia.commands.default import unloggedin # We make use of the helper functions from the default set here. try: permissions = settings.PERMISSION_PLAYER_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS new_player = unloggedin._create_player(caller, playername, password, permissions) if new_player: if settings.MULTISESSION_MODE < 2: default_home = ObjectDB.objects.get_id( settings.DEFAULT_HOME) unloggedin._create_character(caller, new_player, typeclass, default_home, permissions) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, we # won't see any errors at all. caller.msg(dedent(""" |rAn error occurred.|n Please e-mail an admin if the problem persists. Try another password or leave it empty to go back to the login screen. """.strip("\n"))) logger.log_trace() else: text = "" caller.msg("|gWelcome, your new account has been created!|n") caller.msg("", options={"echo": True}) caller.sessionhandler.login(caller, new_player) return text, options
def func(self): "Execute the command" password = self.args self.caller.msg(echo=False) if not hasattr(self.menutree, 'playername'): self.caller.msg( "{rSomething went wrong! Playername not remembered from previous step!{n" ) self.menutree.goto("node2a") return playername = self.menutree.playername if len(password) < 3: # too short password string = "{rYour password must be at least 3 characters or longer." string += "\n\rFor best security, make it at least 8 characters " string += "long, avoid making it a real word and mix numbers " string += "into it.{n" self.caller.msg(string) self.menutree.goto("node2b") return # everything's ok. Create the new player account and possibly the character # depending on the multisession mode from evennia.commands.default import unloggedin # we make use of the helper functions from the default set here. try: permissions = settings.PERMISSION_PLAYER_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS new_player = unloggedin._create_player(self.caller, playername, password, permissions) if new_player: if MULTISESSION_MODE < 2: default_home = ObjectDB.objects.get_id( settings.DEFAULT_HOME) unloggedin._create_character(self.caller, new_player, typeclass, default_home, permissions) # tell the caller everything went well. string = "{gA new account '%s' was created. Now go log in from the menu!{n" self.caller.msg(string % (playername)) self.menutree.goto("START") except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, we # won't see any errors at all. self.caller.msg( "An error occurred. Please e-mail an admin if the problem persists." ) logger.log_trace()
def func(self): "Execute the command" password = self.args self.caller.msg(echo=False) if not hasattr(self.menutree, 'playername'): self.caller.msg("{rSomething went wrong! Playername not remembered from previous step!{n") self.menutree.goto("node2a") return playername = self.menutree.playername if len(password) < 3: # too short password string = "{rYour password must be at least 3 characters or longer." string += "\n\rFor best security, make it at least 8 characters " string += "long, avoid making it a real word and mix numbers " string += "into it.{n" self.caller.msg(string) self.menutree.goto("node2b") return # everything's ok. Create the new player account and possibly the character # depending on the multisession mode from evennia.commands.default import unloggedin # we make use of the helper functions from the default set here. try: permissions = settings.PERMISSION_PLAYER_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS new_player = unloggedin._create_player(self.caller, playername, password, permissions) if new_player: if MULTISESSION_MODE < 2: default_home = ObjectDB.objects.get_id(settings.DEFAULT_HOME) unloggedin._create_character(self.caller, new_player, typeclass, default_home, permissions) # tell the caller everything went well. string = "{gA new account '%s' was created. Now go log in from the menu!{n" self.caller.msg(string % (playername)) self.menutree.goto("START") except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, we # won't see any errors at all. string = "%s\nThis is a bug. Please e-mail an admin if the problem persists." self.caller.msg(string % (traceback.format_exc())) logger.log_errmsg(traceback.format_exc())
def confirm_password(caller, input): """Ask the user to confirm the account's password. The account's password has been saved in the session for the time being, as a hashed version. If the hashed version of the retyped password matches, then the player is created. If not, ask for another password. """ text = "" options = ( { "key": "b", "desc": "Go back to the password selection.", "goto": "create_password", }, { "key": "_default", "desc": "Enter your password.", "goto": "confirm_password", }, ) caller.msg(echo=True) password = input.strip() playername = caller.db._playername first_password = caller.db._password second_password = sha256(password).hexdigest() if first_password != second_password: text = dedent(""" |rThe password you have specified doesn't match the first one.|n Type |yb|n to choose a different password. Or type the confirmation password again. """.strip("\n")) else: # Creates the new player. from evennia.commands.default import unloggedin try: permissions = settings.PERMISSION_PLAYER_DEFAULT player = unloggedin._create_player(caller, playername, password, permissions) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, we # won't see any errors at all. caller.msg( dedent(""" |rAn error occurred.|n Please e-mail an admin if the problem persists. Type |yb|n to go back to the login screen. Or enter another password. """.strip("\n"))) logger.log_trace() else: caller.db._player = player del caller.db._password _login(caller, player) text = "Your new account was successfully created!" text += "\n\n" + text_email_address(player) options = ({ "key": "_default", "desc": "Enter a valid e-mail address.", "goto": "email_address", }, ) return text, options
def create_password(caller, string_input): """Ask the user to create a password. This node is at the end of the menu for account creation. If a proper MULTI_SESSION is configured, a character is also created with the same name (we try to login into it). """ menutree = caller.ndb._menutree text = "" options = ( { "key": "", "exec": lambda caller: caller.msg("", options={"echo": True}), "goto": "start", }, { "key": "_default", "goto": "create_password", }, ) password = string_input.strip() playername = menutree.playername if len(password) < LEN_PASSWD: # The password is too short text = dedent(""" |rYour password must be at least {} characters long.|n Enter another password or leave it empty to go back. """.strip("\n")).format(LEN_PASSWD) else: # Everything's OK. Create the new player account and # possibly the character, depending on the multisession mode from evennia.commands.default import unloggedin # We make use of the helper functions from the default set here. try: permissions = settings.PERMISSION_PLAYER_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS new_player = unloggedin._create_player(caller, playername, password, permissions) if new_player: if settings.MULTISESSION_MODE < 2: default_home = ObjectDB.objects.get_id( settings.DEFAULT_HOME) unloggedin._create_character(caller, new_player, typeclass, default_home, permissions) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, we # won't see any errors at all. caller.msg( dedent(""" |rAn error occurred.|n Please e-mail an admin if the problem persists. Try another password or leave it empty to go back to the login screen. """.strip("\n"))) logger.log_trace() else: text = "" caller.msg("|gWelcome, your new account has been created!|n") caller.msg("", options={"echo": True}) caller.sessionhandler.login(caller, new_player) return text, options
def func(self): """ Uses the Django admin api. Note that unlogged-in commands have a unique position in that their func() receives a session object instead of a source_object like all other types of logged-in commands (this is because there is no object yet before the player has logged in) """ session = self.caller # check for too many login errors too quick. if _throttle(session, maxlim=5, timeout=5 * 60, storage=_LATEST_FAILED_LOGINS): # timeout is 5 minutes. session.msg( "{RВы совершаете слишклм много подключений. Подождите пару минут и попробуйте снова.{n" ) return args = self.args # extract quoted parts parts = [ part.strip() for part in re.split(r"\"|\'", args) if part.strip() ] if len(parts) == 1: # this was (hopefully) due to no quotes being found, or a guest login parts = parts[0].split(None, 1) # Guest login if len(parts) == 1 and parts[0].lower( ) == "guest" and settings.GUEST_ENABLED: try: # Find an available guest name. for playername in settings.GUEST_LIST: if not PlayerDB.objects.filter( username__iexact=playername): break playername = None if playername == None: session.msg( "Все гостевые аккаунты сейчас используются. Попробуйте немного позже." ) return password = "******" % getrandbits(64) home = ObjectDB.objects.get_id(settings.GUEST_HOME) permissions = settings.PERMISSION_GUEST_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS ptypeclass = settings.BASE_GUEST_TYPECLASS new_player = _create_player(session, playername, password, permissions, ptypeclass) if new_player: _create_character(session, new_player, typeclass, home, permissions) session.sessionhandler.login(session, new_player) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. string = "%s\nЭто баг. Напишите пожалуйста на почту администратора." session.msg(string % (traceback.format_exc())) logger.log_errmsg(traceback.format_exc()) finally: return if len(parts) != 2: session.msg( "\n\r Использование (без <>): коннект <имя пользователя> <пароль>. Сокашенные варианты: кон, ко, войти" ) return playername, password = parts # Match account name and check password player = PlayerDB.objects.get_player_from_name(playername) pswd = None if player: pswd = player.check_password(password) if not (player and pswd): # No playername or password match string = "Неверные логин или пароль.\nЕсли в вашем логине или " \ "пароле есть пробелы, поместите их в кавычки." \ "\nЕсли вы новичек, создайте аккаунт при помощи" \ "команды 'создать'." session.msg(string) # this just updates the throttle _throttle(session, storage=_LATEST_FAILED_LOGINS) # calls player hook for a failed login if possible. if player: player.at_failed_login(session) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0] == player.name.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = "{rВы были забанены." \ "\nЕсли считате, что мы были не правы, пишите на е-маил администратора.{x" session.msg(string) session.execute_cmd("quit") return # actually do the login. This will call all other hooks: # session.at_login() # player.at_init() # always called when object is loaded from disk # player.at_pre_login() # player.at_first_login() # only once # player.at_post_login(sessid=sessid) session.sessionhandler.login(session, player)
def func(self): "Do checks and create account" session = self.caller args = self.args.strip() # extract quoted parts parts = [ part.strip() for part in re.split(r"\"|\'", args) if part.strip() ] if len(parts) == 1: # this was (hopefully) due to no quotes being found parts = parts[0].split(None, 1) if len(parts) != 2: string = u"\n Использование (без <>): создать <имя персонажа> <пароль>" \ u"\nЕсли <имя персонажа> или <пароль> содержат пробелы, нужно взять их в ковычки" session.msg(string) return playername, password = parts # sanity checks if not re.findall('^[\w. @+-]+$', playername, re.UNICODE) or not (0 < len(playername) <= 30): # this echoes the restrictions made by django's auth # module (except not allowing spaces, for convenience of # logging in). string = u"\n\r Имя персонажа не должно превышать 30 символов. Имя может содержать только, буквы пробелы, цифры и @/./+/-/_" #string = "\n\r Playername can max be 30 characters or fewer. Letters, spaces, digits and @/./+/-/_ only." session.msg(string) return # strip excessive spaces in playername playername = re.sub(r"\s+", " ", playername).strip() if PlayerDB.objects.filter(username__iexact=playername): # player already exists (we also ignore capitalization here) session.msg(u"Игрок с таким именем '%s' уже есть." % playername) return # Reserve playernames found in GUEST_LIST if settings.GUEST_LIST and playername.lower() in map( str.lower, settings.GUEST_LIST): string = u"\n\r Это имя зарезервировано. Пожалуйста выберите другое имя." session.msg(string) return if not re.findall('^[\w. @+-]+$', password, re.UNICODE) or not (3 < len(password)): string = u"\n\r Пароль должен быть больше трех символов и может состоять только из пробелов, цифр @\.\+\-\_" \ u"\nДля лучшей безопасности выберите пароль от 8 символов " session.msg(string) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0] == playername.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = u"{rТы забанен{x" session.msg(string) session.execute_cmd("quit") return # everything's ok. Create the new player account. try: permissions = settings.PERMISSION_PLAYER_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS new_player = _create_player(session, playername, password, permissions) if new_player: if MULTISESSION_MODE < 2: default_home = ObjectDB.objects.get_id( settings.DEFAULT_HOME) _create_character(session, new_player, typeclass, default_home, permissions) # tell the caller everything went well. string = u"Новый аккаунт создан Добро пожаловать %%USERNAME%%" if " " in playername: string += u"\n\nТеперь можно войти в игру 'connect \"%s\" <пароль>'." else: string += u"\n\nТеперь можно войти в игру 'connect %s <пароль>'." session.msg(string % (playername)) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. string = u"%s\nСлучилась проблема, чиним." session.msg(string % (traceback.format_exc())) logger.log_errmsg(traceback.format_exc())
def func(self): """ Uses the Django admin api. Note that unlogged-in commands have a unique position in that their func() receives a session object instead of a source_object like all other types of logged-in commands (this is because there is no object yet before the player has logged in) """ session = self.caller # check for too many login errors too quick. if _throttle(session, maxlim=5, timeout=5*60, storage=_LATEST_FAILED_LOGINS): # timeout is 5 minutes. session.msg("{RВы совершаете слишклм много подключений. Подождите пару минут и попробуйте снова.{n") return args = self.args # extract quoted parts parts = [part.strip() for part in re.split(r"\"|\'", args) if part.strip()] if len(parts) == 1: # this was (hopefully) due to no quotes being found, or a guest login parts = parts[0].split(None, 1) # Guest login if len(parts) == 1 and parts[0].lower() == "guest" and settings.GUEST_ENABLED: try: # Find an available guest name. for playername in settings.GUEST_LIST: if not PlayerDB.objects.filter(username__iexact=playername): break playername = None if playername == None: session.msg("Все гостевые аккаунты сейчас используются. Попробуйте немного позже.") return password = "******" % getrandbits(64) home = ObjectDB.objects.get_id(settings.GUEST_HOME) permissions = settings.PERMISSION_GUEST_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS ptypeclass = settings.BASE_GUEST_TYPECLASS new_player = _create_player(session, playername, password, permissions, ptypeclass) if new_player: _create_character(session, new_player, typeclass, home, permissions) session.sessionhandler.login(session, new_player) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. string = "%s\nЭто баг. Напишите пожалуйста на почту администратора." session.msg(string % (traceback.format_exc())) logger.log_errmsg(traceback.format_exc()) finally: return if len(parts) != 2: session.msg("\n\r Использование (без <>): коннект <имя пользователя> <пароль>. Сокашенные варианты: кон, ко, войти") return playername, password = parts # Match account name and check password player = PlayerDB.objects.get_player_from_name(playername) pswd = None if player: pswd = player.check_password(password) if not (player and pswd): # No playername or password match string = "Неверные логин или пароль.\nЕсли в вашем логине или " \ "пароле есть пробелы, поместите их в кавычки." \ "\nЕсли вы новичек, создайте аккаунт при помощи" \ "команды 'создать'." session.msg(string) # this just updates the throttle _throttle(session, storage=_LATEST_FAILED_LOGINS) # calls player hook for a failed login if possible. if player: player.at_failed_login(session) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0]==player.name.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = "{rВы были забанены." \ "\nЕсли считате, что мы были не правы, пишите на е-маил администратора.{x" session.msg(string) session.execute_cmd("quit") return # actually do the login. This will call all other hooks: # session.at_login() # player.at_init() # always called when object is loaded from disk # player.at_pre_login() # player.at_first_login() # only once # player.at_post_login(sessid=sessid) session.sessionhandler.login(session, player)
def func(self): "Do checks and create account" session = self.caller args = self.args.strip() # extract quoted parts parts = [part.strip() for part in re.split(r"\"|\'", args) if part.strip()] if len(parts) == 1: # this was (hopefully) due to no quotes being found parts = parts[0].split(None, 1) if len(parts) != 2: string = u"\n Использование (без <>): создать <имя персонажа> <пароль>" \ u"\nЕсли <имя персонажа> или <пароль> содержат пробелы, нужно взять их в ковычки" session.msg(string) return playername, password = parts # sanity checks if not re.findall('^[\w. @+-]+$', playername,re.UNICODE) or not (0 < len(playername) <= 30): # this echoes the restrictions made by django's auth # module (except not allowing spaces, for convenience of # logging in). string = u"\n\r Имя персонажа не должно превышать 30 символов. Имя может содержать только, буквы пробелы, цифры и @/./+/-/_" #string = "\n\r Playername can max be 30 characters or fewer. Letters, spaces, digits and @/./+/-/_ only." session.msg(string) return # strip excessive spaces in playername playername = re.sub(r"\s+", " ", playername).strip() if PlayerDB.objects.filter(username__iexact=playername): # player already exists (we also ignore capitalization here) session.msg(u"Игрок с таким именем '%s' уже есть." % playername) return # Reserve playernames found in GUEST_LIST if settings.GUEST_LIST and playername.lower() in map(str.lower, settings.GUEST_LIST): string = u"\n\r Это имя зарезервировано. Пожалуйста выберите другое имя." session.msg(string) return if not re.findall('^[\w. @+-]+$', password,re.UNICODE) or not (3 < len(password)): string = u"\n\r Пароль должен быть больше трех символов и может состоять только из пробелов, цифр @\.\+\-\_" \ u"\nДля лучшей безопасности выберите пароль от 8 символов " session.msg(string) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0]==playername.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = u"{rТы забанен{x" session.msg(string) session.execute_cmd("quit") return # everything's ok. Create the new player account. try: permissions = settings.PERMISSION_PLAYER_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS new_player = _create_player(session, playername, password, permissions) if new_player: if MULTISESSION_MODE < 2: default_home = ObjectDB.objects.get_id(settings.DEFAULT_HOME) _create_character(session, new_player, typeclass, default_home, permissions) # tell the caller everything went well. string = u"Новый аккаунт создан Добро пожаловать %%USERNAME%%" if " " in playername: string += u"\n\nТеперь можно войти в игру 'connect \"%s\" <пароль>'." else: string += u"\n\nТеперь можно войти в игру 'connect %s <пароль>'." session.msg(string % (playername)) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. string = u"%s\nСлучилась проблема, чиним." session.msg(string % (traceback.format_exc())) logger.log_errmsg(traceback.format_exc())
def func(self): """Do checks and create account""" session = self.caller try: playername, email, password = self.playerinfo except ValueError: string = "\n\r Usage (without <>): create \"<playername>\" <email> <password>" session.msg(string) return if not email or not password: session.msg("\n\r You have to supply an e-mail address followed by a password.") return if not utils.validate_email_address(email): # check so the email at least looks ok. session.msg("'%s' is not a valid e-mail address." % email) return # sanity checks if not re.findall(r"^[\w. @+\-']+$", playername) or not (0 < len(playername) <= 30): # this echoes the restrictions made by django's auth # module (except not allowing spaces, for convenience of # logging in). string = "\n\r Playername can max be 30 characters or fewer. Letters, spaces, digits and @/./+/-/_/' only." session.msg(string) return # strip excessive spaces in playername playername = re.sub(r"\s+", " ", playername).strip() if PlayerDB.objects.filter(username__iexact=playername): # player already exists (we also ignore capitalization here) session.msg("Sorry, there is already a player with the name '%s'." % playername) return if PlayerDB.objects.get_player_from_email(email): # email already set on a player session.msg("Sorry, there is already a player with that email address.") return # Reserve playernames found in GUEST_LIST if settings.GUEST_LIST and playername.lower() in (guest.lower() for guest in settings.GUEST_LIST): string = "\n\r That name is reserved. Please choose another Playername." session.msg(string) return if not re.findall(r"^[\w. @+\-']+$", password) or not (3 < len(password)): string = "\n\r Password should be longer than 3 characers. Letters, spaces, digits and @/./+/-/_/' only." \ "\nFor best security, make it longer than 8 characters. You can also use a phrase of" \ "\nmany words if you enclose the password in double quotes." session.msg(string) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0] == playername.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = "|rYou have been banned and cannot continue from here." \ "\nIf you feel this ban is in error, please email an admin.|x" session.msg(string) session.sessionhandler.disconnect(session, "Good bye! Disconnecting.") return # everything's ok. Create the new player account. try: permissions = settings.PERMISSION_PLAYER_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS new_player = default_unloggedin._create_player(session, playername, password, permissions, email=email) if new_player: if MULTISESSION_MODE < 2: default_home = ObjectDB.objects.get_id(settings.DEFAULT_HOME) default_unloggedin._create_character(session, new_player, typeclass, default_home, permissions) # tell the caller everything went well. string = "A new account '%s' was created. Welcome!" if " " in playername: string += "\n\nYou can now log in with the command 'connect \"%s\" <your password>'." else: string += "\n\nYou can now log with the command 'connect %s <your password>'." session.msg(string % (playername, email)) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. session.msg("An error occurred. Please e-mail an admin if the problem persists.") logger.log_trace() raise
def func(self): """Do checks and create account""" session = self.caller try: playername, email, password = self.playerinfo except ValueError: string = "\n\r Usage (without <>): create \"<playername>\" <email> <password>" session.msg(string) return if not email or not password: session.msg("\n\r You have to supply an e-mail address followed by a password.") return if not utils.validate_email_address(email): # check so the email at least looks ok. session.msg("'%s' is not a valid e-mail address." % email) return # sanity checks if not re.findall(r"^[\w. @+\-']+$", playername) or not (0 < len(playername) <= 30): # this echoes the restrictions made by django's auth # module (except not allowing spaces, for convenience of # logging in). string = "\n\r Playername can max be 30 characters or fewer. Letters, spaces, digits and @/./+/-/_/' only." session.msg(string) return # strip excessive spaces in playername playername = re.sub(r"\s+", " ", playername).strip() if PlayerDB.objects.filter(username__iexact=playername): # player already exists (we also ignore capitalization here) session.msg("Sorry, there is already a player with the name '%s'." % playername) return if PlayerDB.objects.get_player_from_email(email): # email already set on a player session.msg("Sorry, there is already a player with that email address.") return # Reserve playernames found in GUEST_LIST if settings.GUEST_LIST and playername.lower() in (guest.lower() for guest in settings.GUEST_LIST): string = "\n\r That name is reserved. Please choose another Playername." session.msg(string) return if not re.findall(r"^[\w. @+\-']+$", password) or not (3 < len(password)): string = "\n\r Password should be longer than 3 characers. Letters, spaces, digits and @/./+/-/_/' only." \ "\nFor best security, make it longer than 8 characters. You can also use a phrase of" \ "\nmany words if you enclose the password in double quotes." session.msg(string) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0] == playername.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = "|rYou have been banned and cannot continue from here." \ "\nIf you feel this ban is in error, please email an admin.|x" session.msg(string) session.sessionhandler.disconnect(session, "Good bye! Disconnecting.") return # everything's ok. Create the new player account. try: permissions = settings.PERMISSION_PLAYER_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS new_player = default_unloggedin._create_player(session, playername, password, permissions, email=email) if new_player: if MULTISESSION_MODE < 2: default_home = ObjectDB.objects.get_id(settings.DEFAULT_HOME) default_unloggedin._create_character(session, new_player, typeclass, default_home, permissions) # tell the caller everything went well. string = "A new account '%s' was created. Welcome!" if " " in playername: string += "\n\nYou can now log in with the command 'connect \"%s\" <your password>'." else: string += "\n\nYou can now log with the command 'connect %s <your password>'." session.msg(string % (playername, email)) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. raise session.msg("%sAn error occurred. Please e-mail an admin if the problem persists.") logger.log_trace()
def confirm_password(caller, input): """Ask the user to confirm the account's password. The account's password has been saved in the session for the time being, as a hashed version. If the hashed version of the retyped password matches, then the player is created. If not, ask for another password. """ text = "" options = ( { "key": "b", "desc": "Go back to the password selection.", "goto": "create_password", }, { "key": "_default", "desc": "Enter your password.", "goto": "confirm_password", }, ) caller.msg(echo=True) password = input.strip() playername = caller.db._playername first_password = caller.db._password second_password = sha256(password).hexdigest() if first_password != second_password: text = dedent(""" |rThe password you have specified doesn't match the first one.|n Type |yb|n to choose a different password. Or type the confirmation password again. """.strip("\n")) else: # Creates the new player. from evennia.commands.default import unloggedin try: permissions = settings.PERMISSION_PLAYER_DEFAULT player = unloggedin._create_player(caller, playername, password, permissions) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, we # won't see any errors at all. caller.msg(dedent(""" |rAn error occurred.|n Please e-mail an admin if the problem persists. Type |yb|n to go back to the login screen. Or enter another password. """.strip("\n"))) logger.log_trace() else: caller.db._player = player del caller.db._password _login(caller, player) text = "Your new account was successfully created!" text += "\n\n" + text_email_address(player) options = ( { "key": "_default", "desc": "Enter a valid e-mail address.", "goto": "email_address", }, ) return text, options