createsuperuser.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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
  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',
  29. default=True,
  30. help=('Tells Miago to NOT prompt the user for input '
  31. 'of any kind. You must use --username with '
  32. '--noinput, along with an option for any other '
  33. 'required field. Superusers created with '
  34. '--noinput will not be able to log in until '
  35. 'they\'re given a valid password.')),
  36. make_option('--database', action='store', dest='database',
  37. default=DEFAULT_DB_ALIAS,
  38. help=('Specifies the database to use. '
  39. 'Default is "default".')),
  40. )
  41. def execute(self, *args, **options):
  42. self.stdin = options.get('stdin', sys.stdin) # Used for testing
  43. return super(Command, self).execute(*args, **options)
  44. def handle(self, *args, **options):
  45. username = options.get('username')
  46. email = options.get('email')
  47. password = options.get('password')
  48. interactive = options.get('interactive')
  49. verbosity = int(options.get('verbosity', 1))
  50. # Validate initial inputs
  51. if username is not None:
  52. try:
  53. username = username.strip()
  54. validate_username(username)
  55. except ValidationError as e:
  56. self.stderr.write(e.messages[0])
  57. username = None
  58. if email is not None:
  59. try:
  60. email = email.strip()
  61. validate_email(email)
  62. except ValidationError as e:
  63. self.stderr.write(e.messages[0])
  64. email = None
  65. if password is not None:
  66. try:
  67. password = password.strip()
  68. validate_password(password)
  69. except ValidationError as e:
  70. self.stderr.write(e.messages[0])
  71. password = None
  72. if not interactive:
  73. if username and email and password:
  74. # Call User manager's create_superuser using our wrapper
  75. self.create_superuser(username, email, password, verbosity)
  76. else:
  77. try:
  78. if hasattr(self.stdin, 'isatty') and not self.stdin.isatty():
  79. raise NotRunningInTTYException("Not running in a TTY")
  80. # Prompt for username/password, and any other required fields.
  81. # Enclose this whole thing in a try/except to trap for a
  82. # keyboard interrupt and exit gracefully.
  83. while not username:
  84. try:
  85. message = force_str("Enter displayed username: ")
  86. raw_value = input(message).strip()
  87. validate_username(raw_value)
  88. username = raw_value
  89. except ValidationError as e:
  90. self.stderr.write(e.messages[0])
  91. while not email:
  92. try:
  93. raw_value = input("Enter E-mail address: ").strip()
  94. validate_email(raw_value)
  95. email = raw_value
  96. except ValidationError as e:
  97. self.stderr.write(e.messages[0])
  98. while not password:
  99. try:
  100. raw_value = input("Enter password: ").strip()
  101. validate_password(raw_value)
  102. repeat_raw_value = input("Repeat password: ").strip()
  103. if raw_value != repeat_raw_value:
  104. raise ValidationError(
  105. "Entered passwords are different.")
  106. password = raw_value
  107. except ValidationError as e:
  108. self.stderr.write(e.messages[0])
  109. # Call User manager's create_superuser using our wrapper
  110. self.create_superuser(username, email, password, verbosity)
  111. except KeyboardInterrupt:
  112. self.stderr.write("\nOperation cancelled.")
  113. sys.exit(1)
  114. except NotRunningInTTYException:
  115. self.stdout.write(
  116. "Superuser creation skipped due to not running in a TTY. "
  117. "You can run `manage.py createsuperuser` in your project "
  118. "to create one manually."
  119. )
  120. def create_superuser(self, username, email, password, verbosity):
  121. try:
  122. User = get_user_model()
  123. user = User.objects.create_superuser(username, email, password)
  124. if verbosity >= 1:
  125. message = "Superuser #%(pk)s has been created successfully."
  126. self.stdout.write(message % {'pk': user.pk})
  127. except ValidationError as e:
  128. self.stderr.write(e.messages[0])
  129. except IntegrityError as e:
  130. self.stderr.write(e.messages[0])