changepassword.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. from __future__ import unicode_literals
  2. import getpass
  3. from django.contrib.auth import get_user_model
  4. from django.contrib.auth.password_validation import validate_password
  5. from django.core.exceptions import ValidationError
  6. from django.core.management.base import BaseCommand, CommandError
  7. from django.db import DEFAULT_DB_ALIAS
  8. from django.utils.encoding import force_str
  9. class Command(BaseCommand):
  10. help = "Change a user's password for django.contrib.auth."
  11. requires_migrations_checks = True
  12. requires_system_checks = False
  13. def _get_pass(self, prompt="Password: "):
  14. p = getpass.getpass(prompt=force_str(prompt))
  15. if not p:
  16. raise CommandError("aborted")
  17. return p
  18. def add_arguments(self, parser):
  19. parser.add_argument(
  20. 'username', nargs='?',
  21. help='Username to change password for; by default, it\'s the current username.',
  22. )
  23. parser.add_argument(
  24. '--database', action='store', dest='database',
  25. default=DEFAULT_DB_ALIAS,
  26. help='Specifies the database to use. Default is "default".',
  27. )
  28. def handle(self, *args, **options):
  29. if options['username']:
  30. username = options['username']
  31. else:
  32. username = getpass.getuser()
  33. UserModel = get_user_model()
  34. try:
  35. u = UserModel._default_manager.using(options['database']).get(**{
  36. UserModel.USERNAME_FIELD: username
  37. })
  38. except UserModel.DoesNotExist:
  39. raise CommandError("user '%s' does not exist" % username)
  40. self.stdout.write("Changing password for user '%s'\n" % u)
  41. MAX_TRIES = 3
  42. count = 0
  43. p1, p2 = 1, 2 # To make them initially mismatch.
  44. password_validated = False
  45. while (p1 != p2 or not password_validated) and count < MAX_TRIES:
  46. p1 = self._get_pass()
  47. p2 = self._get_pass("Password (again): ")
  48. if p1 != p2:
  49. self.stdout.write("Passwords do not match. Please try again.\n")
  50. count += 1
  51. # Don't validate passwords that don't match.
  52. continue
  53. try:
  54. validate_password(p2, u)
  55. except ValidationError as err:
  56. self.stderr.write('\n'.join(err.messages))
  57. count += 1
  58. else:
  59. password_validated = True
  60. if count == MAX_TRIES:
  61. raise CommandError("Aborting password change for user '%s' after %s attempts" % (u, count))
  62. u.set_password(p1)
  63. u.save()
  64. return "Password changed successfully for user '%s'" % u