]> git.ipfire.org Git - ipfire.org.git/blame - src/backend/bugzilla.py
accounts: Add Bugzilla API to delete accounts in Bugzilla
[ipfire.org.git] / src / backend / bugzilla.py
CommitLineData
26ccb61a
MT
1#!/usr/bin/python3
2
3import json
4import urllib.parse
5
6from . import misc
7from .decorators import *
8
9class BugzillaError(Exception):
10 pass
11
12class Bugzilla(misc.Object):
13 def init(self, api_key=None):
14 if api_key is None:
15 api_key = self.settings.get("bugzilla-api-key")
16
17 # Store the API key
18 self.api_key = api_key
19
20 @property
21 def url(self):
22 """
23 Returns the base URL of a Bugzilla instance
24 """
25 return self.settings.get("bugzilla-url")
26
27 def make_url(self, *args, **kwargs):
28 """
29 Composes a URL based on the base URL
30 """
31 url = urllib.parse.urljoin(self.url, *args)
32
33 # Append any query arguments
34 if kwargs:
35 url = "%s?%s" % (url, urllib.parse.urlencode(kwargs))
36
37 return url
38
39 async def _request(self, method, url, data=None):
40 if data is None:
41 data = {}
42
43 # Headers
44 headers = {
45 # Authenticate all requests
46 "X-BUGZILLA-API-KEY" : self.api_key,
47 }
48
49 # Make the URL
50 url = self.make_url(url)
51
52 # Fallback authentication because some API endpoints
53 # do not accept the API key in the header
54 data |= { "api_key" : self.api_key }
55
56 # Encode body
57 body = None
58
59 # For GET requests, append query arguments
60 if method == "GET":
61 if data:
62 url = "%s?%s" % (url, urllib.parse.urlencode(data))
63
64 # For POST/PUT encode all arguments as JSON
65 elif method in ("POST", "PUT"):
66 headers |= {
67 "Content-Type" : "application/json",
68 }
69
70 body = json.dumps(data)
71
72 # Send the request and wait for a response
73 res = await self.backend.http_client.fetch(
74 url, method=method, headers=headers, body=body)
75
76 # Decode JSON response
77 body = json.loads(res.body)
78
79 # Check for any errors
80 if "error" in body:
81 # Fetch code and message
82 code, message = body.get("code"), body.get("message")
83
84 # Handle any so far unhandled errors
85 raise BugzillaError(message)
86
87 # Return an empty response
88 return body
89
90 async def get_user(self, uid):
91 """
92 Fetches a user from Bugzilla
93 """
94 response = await self._request("GET", "/rest/user/%s" % uid)
95
96 # Return the user object
97 for data in response.get("users"):
98 return User(self.backend, data)
99
100
101
102class User(misc.Object):
103 def init(self, data):
104 self.data = data
105
106 @property
107 def id(self):
108 return self.data.get("id")
109
110 async def _update(self, **kwargs):
111 # Send the request
112 await self.backend.bugzilla._request("PUT", "/rest/user/%s" % self.id, **kwargs)
113
114 # XXX apply changes to the User object?
115
116 async def disable(self, text=None):
117 """
118 Disables this user
119 """
120 if not text:
121 text = "DISABLED"
122
123 # Update the user
124 await self._update(data={
125 "login_denied_text" : text,
126 })