Coverage for dak/add_user.py: 26%

81 statements  

« prev     ^ index     » next       coverage.py v7.6.0, created at 2026-08-03 16:46 +0000

1""" 

2Add a user to to the uid/maintainer/fingerprint table and 

3add his key to the GPGKeyring 

4 

5@contact: Debian FTP Master <ftpmaster@debian.org> 

6@copyright: 2004, 2009 Joerg Jaspert <joerg@ganneff.de> 

7@license: GNU General Public License version 2 or later 

8""" 

9 

10################################################################################ 

11# <elmo> wow, sounds like it'll be a big step up.. configuring dak on a 

12# new machine even scares me :) 

13################################################################################ 

14 

15# You don't want to read this script if you know python. 

16# I know what I say. I dont know python and I wrote it. So go and read some other stuff. 

17 

18import subprocess 

19import sys 

20from typing import NoReturn 

21 

22import apt_pkg 

23 

24from daklib import utils 

25from daklib.dbconn import DBConn, get_active_keyring_paths, get_or_set_uid 

26from daklib.regexes import ( 

27 re_gpg_fingerprint_colon, 

28 re_user_address, 

29 re_user_mails, 

30 re_user_name, 

31) 

32 

33################################################################################ 

34 

35Cnf = None 

36Logger = None 

37 

38################################################################################ 

39 

40 

41def usage(exit_code: int = 0) -> NoReturn: 

42 print( 

43 """Usage: add-user [OPTION]... 

44Adds a new user to the dak databases and keyrings 

45 

46 -k, --key keyid of the User 

47 -u, --user userid of the User 

48 -h, --help show this help and exit.""" 

49 ) 

50 sys.exit(exit_code) 

51 

52 

53################################################################################ 

54 

55 

56def main() -> None: 

57 global Cnf 

58 keyrings = None 

59 

60 Cnf = utils.get_conf() 

61 

62 Arguments = [ 

63 ("h", "help", "Add-User::Options::Help"), 

64 ("k", "key", "Add-User::Options::Key", "HasArg"), 

65 ("u", "user", "Add-User::Options::User", "HasArg"), 

66 ] 

67 

68 for i in ["help"]: 

69 key = "Add-User::Options::%s" % i 

70 if key not in Cnf: 70 ↛ 68line 70 didn't jump to line 68 because the condition on line 70 was always true

71 Cnf[key] = "" # type: ignore[index] 

72 

73 apt_pkg.parse_commandline(Cnf, Arguments, sys.argv) # type: ignore[attr-defined] 

74 

75 Options = Cnf.subtree("Add-User::Options") # type: ignore[attr-defined] 

76 if Options["help"]: 76 ↛ 79line 76 didn't jump to line 79 because the condition on line 76 was always true

77 usage() 

78 

79 session = DBConn().session() 

80 

81 if not keyrings: 

82 keyrings = get_active_keyring_paths() 

83 

84 cmd = [ 

85 "gpg", 

86 "--with-colons", 

87 "--no-secmem-warning", 

88 "--no-auto-check-trustdb", 

89 "--with-fingerprint", 

90 "--no-default-keyring", 

91 ] 

92 cmd.extend(utils.gpg_keyring_args(keyrings)) 

93 cmd.extend(["--list-key", "--", Cnf["Add-User::Options::Key"]]) 

94 output = subprocess.check_output(cmd, text=True).rstrip() 

95 m = re_gpg_fingerprint_colon.search(output) 

96 if not m: 

97 print(output) 

98 utils.fubar( 

99 "0x%s: (1) No fingerprint found in gpg output but it returned 0?\n%s" 

100 % ( 

101 Cnf["Add-User::Options::Key"], 

102 utils.prefix_multi_line_string(output, " [GPG output:] "), 

103 ) 

104 ) 

105 primary_key = m.group(1) 

106 primary_key = primary_key.replace(" ", "") 

107 

108 uid = "" 

109 if "Add-User::Options::User" in Cnf and Cnf["Add-User::Options::User"]: 

110 uid = Cnf["Add-User::Options::User"] 

111 name = Cnf["Add-User::Options::User"] 

112 else: 

113 u = re_user_address.search(output) 

114 if not u: 

115 print(output) 

116 utils.fubar( 

117 "0x%s: (2) No userid found in gpg output but it returned 0?\n%s" 

118 % ( 

119 Cnf["Add-User::Options::Key"], 

120 utils.prefix_multi_line_string(output, " [GPG output:] "), 

121 ) 

122 ) 

123 uid = u.group(1) 

124 n = re_user_name.search(output) 

125 assert n is not None 

126 name = n.group(1) 

127 

128 # Look for all email addresses on the key. 

129 emails = [] 

130 for line in output.split("\n"): 

131 e = re_user_mails.search(line) 

132 if not e: 

133 continue 

134 emails.append(e.group(2)) 

135 

136 print( 

137 "0x%s -> %s <%s> -> %s -> %s" 

138 % (Cnf["Add-User::Options::Key"], name, emails[0], uid, primary_key) 

139 ) 

140 

141 prompt = "Add user %s with above data (y/N) ? " % (uid) 

142 if utils.input_or_exit(prompt).lower() != "y": 

143 return 

144 

145 # Create an account for the user? 

146 summary = "" 

147 

148 # Now add user to the database. 

149 # Note that we provide a session, so we're responsible for committing 

150 uidobj = get_or_set_uid(uid, session=session) 

151 uid_id = uidobj.uid_id 

152 session.commit() 

153 

154 # Lets add user to the email-whitelist file if its configured. 

155 if "Dinstall::MailWhiteList" in Cnf and Cnf["Dinstall::MailWhiteList"] != "": 

156 with open(Cnf["Dinstall::MailWhiteList"], "a") as f: 

157 f.writelines(mail + "\n" for mail in emails) 

158 

159 print( 

160 "Added:\nUid:\t %s (ID: %s)\nMaint:\t %s\nFP:\t %s" 

161 % (uid, uid_id, name, primary_key) 

162 ) 

163 

164 # Should we send mail to the newly added user? 

165 if Cnf.find_b("Add-User::SendEmail"): 

166 mail = name + "<" + emails[0] + ">" 

167 Subst = {} 

168 Subst["__NEW_MAINTAINER__"] = mail 

169 Subst["__UID__"] = uid 

170 Subst["__KEYID__"] = Cnf["Add-User::Options::Key"] 

171 Subst["__PRIMARY_KEY__"] = primary_key 

172 Subst["__FROM_ADDRESS__"] = Cnf["Dinstall::MyEmailAddress"] 

173 Subst["__ADMIN_ADDRESS__"] = Cnf["Dinstall::MyAdminAddress"] 

174 Subst["__HOSTNAME__"] = Cnf["Dinstall::MyHost"] 

175 Subst["__DISTRO__"] = Cnf["Dinstall::MyDistribution"] 

176 Subst["__SUMMARY__"] = summary 

177 new_add_message = utils.TemplateSubst( 

178 Subst, Cnf["Dir::Templates"] + "/add-user.added" 

179 ) 

180 utils.send_mail(new_add_message)