Coverage for app/venv/lib/python3.14/site-packages/weblate/auth/management/commands/createadmin.py: 58%

53 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 07:15 +0000

1# Copyright © Michal Čihař <michal@weblate.org> 

2# 

3# SPDX-License-Identifier: GPL-3.0-or-later 

4from __future__ import annotations 

5 

6from typing import TYPE_CHECKING 

7 

8from django.core.management.base import CommandError 

9from django.db.models import Q 

10 

11from weblate.auth.models import User 

12from weblate.utils.backup import make_password 

13from weblate.utils.management.base import BaseCommand 

14 

15if TYPE_CHECKING: 15 ↛ 16line 15 didn't jump to line 16 because the condition on line 15 was never true

16 from django.core.management.base import CommandParser 

17 

18 

19class Command(BaseCommand): 

20 help = "setups admin user with random password" 

21 

22 def add_arguments(self, parser: CommandParser) -> None: 

23 parser.add_argument( 

24 "--password", 

25 default=None, 

26 help="Password to set, random is generated if not specified", 

27 ) 

28 parser.add_argument( 

29 "--no-password", 

30 action="store_true", 

31 default=False, 

32 help="Do not set password at all (useful with --update)", 

33 ) 

34 parser.add_argument( 

35 "--username", default="admin", help='Admin username, defaults to "admin"' 

36 ) 

37 parser.add_argument( 

38 "--email", 

39 default="admin@example.com", 

40 help='Admin email, defaults to "admin@example.com"', 

41 ) 

42 parser.add_argument( 

43 "--name", 

44 default="Weblate Admin", 

45 help='Admin name, defaults to "Weblate Admin"', 

46 ) 

47 parser.add_argument( 

48 "--update", 

49 action="store_true", 

50 default=False, 

51 help="Change password for this account if exists", 

52 ) 

53 

54 def handle(self, *args, **options) -> None: 

55 """ 

56 Create admin account with admin password. 

57 

58 This is useful mostly for setup inside appliances, when user wants to be able to 

59 login remotely and change password then. 

60 """ 

61 email = options["email"] 

62 username = options["username"] 

63 if not email: 63 ↛ 64line 63 didn't jump to line 64 because the condition on line 63 was never true

64 email = "admin@example.com" 

65 self.stdout.write(f"Blank e-mail for admin, using {email} instead!") 

66 matching_users = User.objects.filter(Q(username=username) | Q(email=email)) 

67 

68 if len(matching_users) == 0: 68 ↛ 70line 68 didn't jump to line 70 because the condition on line 68 was always true

69 user = None 

70 elif len(matching_users) == 1: 

71 user = matching_users[0] 

72 else: 

73 for user in matching_users: 

74 self.stderr.write( 

75 f"Found matching user: username={user.username} email={user.email}" 

76 ) 

77 msg = "Multiple users matched given parameters!" 

78 raise CommandError(msg) 

79 

80 if user and not options["update"]: 80 ↛ 81line 80 didn't jump to line 81 because the condition on line 80 was never true

81 msg = f"User {username} already exists, specify --update to update existing" 

82 raise CommandError(msg) 

83 

84 if options["no_password"]: 84 ↛ 85line 84 didn't jump to line 85 because the condition on line 84 was never true

85 password = None 

86 elif options["password"]: 86 ↛ 89line 86 didn't jump to line 89 because the condition on line 86 was always true

87 password = options["password"] 

88 else: 

89 password = make_password(13) 

90 self.stdout.write(f"Using generated password: {password}") 

91 

92 if user and options["update"]: 92 ↛ 93line 92 didn't jump to line 93 because the condition on line 92 was never true

93 self.stdout.write(f"Updating user {user.username}") 

94 user.email = email 

95 if password is not None and not user.check_password(password): 

96 user.set_password(password) 

97 else: 

98 self.stdout.write(f"Creating user {username}") 

99 user = User.objects.create_user(username, email, password) 

100 user.full_name = options["name"] 

101 user.is_superuser = True 

102 user.is_active = True 

103 user.save()