createsuperuser.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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. # Validate initial inputs
  45. if username is not None:
  46. try:
  47. username = username.strip()
  48. validate_username(username)
  49. except ValidationError as e:
  50. self.stderr.write(e.messages[0])
  51. username = None
  52. if email is not None:
  53. try:
  54. email = email.strip()
  55. validate_email(email)
  56. except ValidationError as e:
  57. self.stderr.write(e.messages[0])
  58. email = None
  59. if password is not None:
  60. try:
  61. password = password.strip()
  62. validate_password(password)
  63. except ValidationError as e:
  64. self.stderr.write(e.messages[0])
  65. password = None
  66. if not interactive:
  67. if username and email and password:
  68. # Call User manager's create_superuser using our wrapper
  69. self.create_superuser(username, email, password)
  70. else:
  71. try:
  72. if hasattr(self.stdin, 'isatty') and not self.stdin.isatty():
  73. raise NotRunningInTTYException("Not running in a TTY")
  74. # Prompt for username/password, and any other required fields.
  75. # Enclose this whole thing in a try/except to trap for a
  76. # keyboard interrupt and exit gracefully.
  77. while not username:
  78. try:
  79. message = force_str("Enter displayed username: ")
  80. raw_value = input(message).strip()
  81. validate_username(raw_value)
  82. username = raw_value
  83. except ValidationError as e:
  84. self.stderr.write(e.messages[0])
  85. while not email:
  86. try:
  87. raw_value = input("Enter E-mail address: ").strip()
  88. validate_email(raw_value)
  89. email = raw_value
  90. except ValidationError as e:
  91. self.stderr.write(e.messages[0])
  92. while not password:
  93. try:
  94. raw_value = input("Enter password: ").strip()
  95. validate_password(raw_value)
  96. repeat_raw_value = input("Repeat password: ").strip()
  97. if raw_value != repeat_raw_value:
  98. raise ValidationError(
  99. "Entered passwords are different.")
  100. password = raw_value
  101. except ValidationError as e:
  102. self.stderr.write(e.messages[0])
  103. # Call User manager's create_superuser using our wrapper
  104. self.create_superuser(username, email, password)
  105. except KeyboardInterrupt:
  106. self.stderr.write("\nOperation cancelled.")
  107. sys.exit(1)
  108. except NotRunningInTTYException:
  109. self.stdout.write(
  110. "Superuser creation skipped due to not running in a TTY. "
  111. "You can run `manage.py createsuperuser` in your project "
  112. "to create one manually."
  113. )
  114. def create_superuser(self, username, email, password):
  115. try:
  116. User = get_user_model()
  117. user = User.objects.create_superuser(username, email, password)
  118. message = "Superuser #%(pk)s has been created successfully."
  119. self.stdout.write(message % {'pk': user.pk})
  120. except ValidationError as e:
  121. self.stderr.write(e.messages[0])
  122. except IntegrityError as e:
  123. self.stderr.write(e.messages[0])