createsuperuser.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. """
  2. Misago-native rehash of Django's createsuperuser command that
  3. works with double authentication fields on user model
  4. """
  5. from getpass import getpass
  6. from optparse import make_option
  7. import sys
  8. from django.contrib.auth import get_user_model
  9. from django.core.exceptions import ValidationError
  10. from django.core.management.base import BaseCommand
  11. from django.db import DEFAULT_DB_ALIAS, IntegrityError
  12. from django.utils.encoding import force_str
  13. from django.utils.six.moves import input
  14. from misago.users.validators import (validate_email, validate_username,
  15. validate_password)
  16. class NotRunningInTTYException(Exception):
  17. pass
  18. class Command(BaseCommand):
  19. help = 'Used to create a superuser.'
  20. def __init__(self, *args, **kwargs):
  21. super(Command, self).__init__(*args, **kwargs)
  22. self.option_list = BaseCommand.option_list + (
  23. make_option('--username', dest='username', default=None,
  24. help='Specifies the username for the superuser.'),
  25. make_option('--email', dest='email', default=None,
  26. help='Specifies the username for the superuser.'),
  27. make_option('--password', dest='password', default=None,
  28. help='Specifies the username for the superuser.'),
  29. make_option('--noinput', action='store_false', dest='interactive',
  30. default=True,
  31. help=('Tells Miago to NOT prompt the user for input '
  32. 'of any kind. You must use --username with '
  33. '--noinput, along with an option for any other '
  34. 'required field. Superusers created with '
  35. '--noinput will not be able to log in until '
  36. 'they\'re given a valid password.')),
  37. make_option('--database', action='store', dest='database',
  38. default=DEFAULT_DB_ALIAS,
  39. help=('Specifies the database to use. '
  40. 'Default is "default".')),
  41. )
  42. def execute(self, *args, **options):
  43. self.stdin = options.get('stdin', sys.stdin) # Used for testing
  44. return super(Command, self).execute(*args, **options)
  45. def handle(self, *args, **options):
  46. username = options.get('username')
  47. email = options.get('email')
  48. password = options.get('password')
  49. interactive = options.get('interactive')
  50. verbosity = int(options.get('verbosity', 1))
  51. # Validate initial inputs
  52. if username is not None:
  53. try:
  54. username = username.strip()
  55. validate_username(username)
  56. except ValidationError as e:
  57. self.stderr.write(e.messages[0])
  58. username = None
  59. if email is not None:
  60. try:
  61. email = email.strip()
  62. validate_email(email)
  63. except ValidationError as e:
  64. self.stderr.write(e.messages[0])
  65. email = None
  66. if password is not None:
  67. try:
  68. password = password.strip()
  69. validate_password(password)
  70. except ValidationError as e:
  71. self.stderr.write(e.messages[0])
  72. password = None
  73. if not interactive:
  74. if username and email and password:
  75. # Call User manager's create_superuser using our wrapper
  76. self.create_superuser(username, email, password, verbosity)
  77. else:
  78. try:
  79. if hasattr(self.stdin, 'isatty') and not self.stdin.isatty():
  80. raise NotRunningInTTYException("Not running in a TTY")
  81. # Prompt for username/password, and any other required fields.
  82. # Enclose this whole thing in a try/except to trap for a
  83. # keyboard interrupt and exit gracefully.
  84. while not username:
  85. try:
  86. message = force_str("Enter displayed username: ")
  87. raw_value = input(message).strip()
  88. validate_username(raw_value)
  89. username = raw_value
  90. except ValidationError as e:
  91. self.stderr.write(e.messages[0])
  92. while not email:
  93. try:
  94. raw_value = input("Enter E-mail address: ").strip()
  95. validate_email(raw_value)
  96. email = raw_value
  97. except ValidationError as e:
  98. self.stderr.write(e.messages[0])
  99. while not password:
  100. try:
  101. raw_value = getpass("Enter password: ").strip()
  102. validate_password(raw_value)
  103. repeat_raw_value = getpass("Repeat password: ").strip()
  104. if raw_value != repeat_raw_value:
  105. raise ValidationError(
  106. "Entered passwords are different.")
  107. password = raw_value
  108. except ValidationError as e:
  109. self.stderr.write(e.messages[0])
  110. # Call User manager's create_superuser using our wrapper
  111. self.create_superuser(username, email, password, verbosity)
  112. except KeyboardInterrupt:
  113. self.stderr.write("\nOperation cancelled.")
  114. sys.exit(1)
  115. except NotRunningInTTYException:
  116. self.stdout.write(
  117. "Superuser creation skipped due to not running in a TTY. "
  118. "You can run `manage.py createsuperuser` in your project "
  119. "to create one manually."
  120. )
  121. def create_superuser(self, username, email, password, verbosity):
  122. try:
  123. User = get_user_model()
  124. user = User.objects.create_superuser(username, email, password,
  125. set_default_avatar=True)
  126. if verbosity >= 1:
  127. message = "Superuser #%(pk)s has been created successfully."
  128. self.stdout.write(message % {'pk': user.pk})
  129. except ValidationError as e:
  130. self.stderr.write(e.messages[0])
  131. except IntegrityError as e:
  132. self.stderr.write(e.messages[0])