createsuperuser.py 6.1 KB

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