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
« 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
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"""
10################################################################################
11# <elmo> wow, sounds like it'll be a big step up.. configuring dak on a
12# new machine even scares me :)
13################################################################################
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.
18import subprocess
19import sys
20from typing import NoReturn
22import apt_pkg
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)
33################################################################################
35Cnf = None
36Logger = None
38################################################################################
41def usage(exit_code: int = 0) -> NoReturn:
42 print(
43 """Usage: add-user [OPTION]...
44Adds a new user to the dak databases and keyrings
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)
53################################################################################
56def main() -> None:
57 global Cnf
58 keyrings = None
60 Cnf = utils.get_conf()
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 ]
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]
73 apt_pkg.parse_commandline(Cnf, Arguments, sys.argv) # type: ignore[attr-defined]
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()
79 session = DBConn().session()
81 if not keyrings:
82 keyrings = get_active_keyring_paths()
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(" ", "")
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)
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))
136 print(
137 "0x%s -> %s <%s> -> %s -> %s"
138 % (Cnf["Add-User::Options::Key"], name, emails[0], uid, primary_key)
139 )
141 prompt = "Add user %s with above data (y/N) ? " % (uid)
142 if utils.input_or_exit(prompt).lower() != "y":
143 return
145 # Create an account for the user?
146 summary = ""
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()
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)
159 print(
160 "Added:\nUid:\t %s (ID: %s)\nMaint:\t %s\nFP:\t %s"
161 % (uid, uid_id, name, primary_key)
162 )
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)