]> git.ipfire.org Git - people/jschlag/pbs.git/blob - src/buildservice/keys.py
Refactor Bugzilla URL generation
[people/jschlag/pbs.git] / src / buildservice / keys.py
1 #!/usr/bin/python
2
3 import datetime
4 import gpgme
5 import io
6 import os
7 import shutil
8 import tempfile
9
10 from . import base
11
12 from .decorators import *
13
14 def read_key(data):
15 data = str(data)
16 data = io.BytesIO(data)
17
18 tmpdir = tempfile.mkdtemp()
19 os.environ["GNUPGHOME"] = tmpdir
20
21 try:
22 ctx = gpgme.Context()
23 res = ctx.import_(data)
24
25 assert len(res.imports) == 1
26 (fpr, trash_a, trash_b) = res.imports[0]
27
28 key = ctx.get_key(fpr)
29 assert key
30
31 return fpr, key
32
33 finally:
34 shutil.rmtree(tmpdir)
35 del os.environ["GNUPGHOME"]
36
37
38 class Keys(base.Object):
39 def create(self, data):
40 fingerprint, key = read_key(data)
41
42 # Search for duplicates and just update them.
43 k = pakfire.keys.get_by_fpr(fingerprint)
44 if k:
45 k.update(data)
46 return k
47
48 # Insert new into the database.
49 res = self.db.get("INSERT INTO keys(fingerprint, uids, data) \
50 VALUES(%s, %s, %s) RETURNING *", fingerprint, ", ".join([u.uid for u in key.uids]), data)
51
52 key = Key(self.backend, res.id, data=res)
53 key.update(data)
54
55 return key
56
57 def get_all(self):
58 query = self.db.query("SELECT id FROM keys ORDER BY uids")
59
60 keys = []
61 for key in query:
62 key = Key(self.pakfire, key.id)
63 keys.append(key)
64
65 return keys
66
67 def get_by_id(self, id):
68 key = self.db.get("SELECT id FROM keys WHERE id = %s", id)
69 if not key:
70 return
71
72 return Key(self.pakfire, key.id)
73
74 def get_by_fpr(self, fpr):
75 fpr = "%%%s" % fpr
76
77 key = self.db.get("SELECT id FROM keys WHERE fingerprint LIKE %s", fpr)
78 if not key:
79 return
80
81 return Key(self.pakfire, key.id)
82
83
84 class Key(base.DataObject):
85 table = "keys"
86
87 def update(self, data):
88 fingerprint, key = read_key(data)
89
90 # First, delete all subkeys.
91 self.db.execute("DELETE FROM keys_subkeys WHERE key_id = %s", self.id)
92
93 for subkey in key.subkeys:
94 time_created = datetime.datetime.fromtimestamp(subkey.timestamp)
95 if subkey.expires:
96 time_expires = datetime.datetime.fromtimestamp(subkey.expires)
97 else:
98 time_expires = None # Key does never expire.
99
100 algo = None
101 if subkey.pubkey_algo == gpgme.PK_RSA:
102 algo = "RSA/%s" % subkey.length
103
104 self.db.execute("INSERT INTO keys_subkeys(key_id, fingerprint, \
105 time_created, time_expires, algo) VALUES(%s, %s, %s, %s, %s)",
106 self.id, subkey.keyid, time_created, time_expires, algo)
107
108 self.db.execute("UPDATE keys SET fingerprint = %s, uids = %s, data = %s WHERE id = %s",
109 fingerprint, ", ".join([u.uid for u in key.uids]), data, self.id)
110
111 def can_be_deleted(self):
112 ret = self.db.query("SELECT id FROM repositories WHERE key_id = %s", self.id)
113
114 if ret:
115 return False
116
117 return True
118
119 def delete(self):
120 assert self.can_be_deleted()
121
122 self.db.execute("DELETE FROM keys_subkeys WHERE key_id = %s", self.id)
123 self.db.execute("DELETE FROM keys WHERE id = %s", self.id)
124
125 @property
126 def fingerprint(self):
127 return self.data.fingerprint[-16:]
128
129 @property
130 def uids(self):
131 return self.data.uids.split(", ")
132
133 @property
134 def key(self):
135 return self.data.data
136
137 @lazy_property
138 def subkeys(self):
139 res = self.db.query("SELECT * FROM keys_subkeys WHERE key_id = %s ORDER BY time_created", self.id)
140
141 subkeys = []
142 for row in res:
143 subkey = Subkey(self.backend, row.id, data=row)
144 subkeys.append(subkey)
145
146 return sorted(subkeys)
147
148
149 class Subkey(base.DataObject):
150 table = "keys_subkeys"
151
152 def __lt__(self, other):
153 if isinstance(other, self.__class__):
154 return self.time_created < other.time_created
155
156 @property
157 def fingerprint(self):
158 return self.data.fingerprint
159
160 @property
161 def time_created(self):
162 return self.data.time_created
163
164 @property
165 def time_expires(self):
166 return self.data.time_expires
167
168 @property
169 def expired(self):
170 return self.time_expires <= datetime.datetime.utcnow()
171
172 @property
173 def algo(self):
174 return self.data.algo