]>
Commit | Line | Data |
---|---|---|
2c361abc MT |
1 | #!/usr/bin/python |
2 | ||
3 | import hashlib | |
4 | import hmac | |
5 | import json | |
6 | import tornado.httpclient | |
7 | import tornado.gen | |
8 | import urllib | |
9 | import urlparse | |
10 | ||
11 | from misc import Object | |
12 | ||
13 | class ZeiterfassungClient(Object): | |
14 | algorithm = "Zeiterfassung-HMAC-SHA512" | |
15 | ||
16 | def init(self): | |
17 | self.url = self.settings.get("zeiterfassung_url") | |
18 | ||
19 | # API credentials | |
20 | self.api_key = self.settings.get("zeiterfassung_api_key") | |
21 | self.api_secret = self.settings.get("zeiterfassung_api_secret") | |
22 | ||
23 | # Check if all configuration values are set | |
24 | if not all((self.url, self.api_key, self.api_secret)): | |
25 | raise RuntimeError("%s is not configured" % self.__class__.__name__) | |
26 | ||
27 | # Create HTTPClient | |
28 | self.http_client = tornado.httpclient.AsyncHTTPClient( | |
29 | defaults = { | |
30 | "User-Agent" : "IPFireWebApp", | |
31 | } | |
32 | ) | |
33 | ||
34 | def _make_signature(self, method, path, body): | |
35 | # Empty since we only support POST | |
36 | canonical_query = "" | |
37 | ||
38 | # Put everything together | |
39 | string_to_sign = "\n".join(( | |
40 | method, path, canonical_query, | |
41 | )).encode("utf-8") + body | |
42 | ||
43 | # Compute HMAC | |
44 | h = hmac.new(self.api_secret.encode("utf-8"), string_to_sign, hashlib.sha512) | |
45 | ||
46 | return h.hexdigest() | |
47 | ||
48 | @tornado.gen.coroutine | |
49 | def send_request(self, path, **kwargs): | |
50 | url = urlparse.urljoin(self.url, path) | |
51 | ||
52 | # Query arguments are all keyword arguments | |
53 | arguments = kwargs | |
54 | ||
55 | request = tornado.httpclient.HTTPRequest(url, method="POST") | |
56 | request.body = urllib.urlencode(arguments) | |
57 | ||
58 | # Compose the signature | |
59 | signature = self._make_signature("POST", path, request.body) | |
60 | ||
61 | # Add authorization header | |
62 | request.headers["Authorization"] = " ".join( | |
63 | (self.algorithm, self.api_key, signature) | |
64 | ) | |
65 | ||
66 | # Send the request | |
67 | response = yield self.http_client.fetch(request) | |
68 | ||
69 | # Decode the JSON response | |
70 | d = json.loads(response.body.decode()) | |
71 | ||
72 | raise tornado.gen.Return(d) |