OLD | NEW |
---|---|
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import calendar | 5 import calendar |
6 from datetime import datetime | 6 from datetime import datetime |
7 import functools | |
7 import hashlib | 8 import hashlib |
8 import json | 9 import json |
9 import logging | 10 import logging |
11 import os | |
10 | 12 |
11 from google.appengine.api import memcache | 13 from google.appengine.api import memcache |
12 from google.appengine.api import users | 14 from google.appengine.api import users |
15 from google.appengine.api import app_identity | |
13 | 16 |
14 from shared.config import VALID_EMAIL_RE | 17 from shared.config import HOST_ACLS |
15 | 18 |
16 compressed_separators = (',', ':') | 19 compressed_separators = (',', ':') |
17 minutes_per_day = 24 * 60 | 20 minutes_per_day = 24 * 60 |
18 | 21 |
19 def cronjob(cronjob_handler): | 22 def cronjob(cronjob_handler): |
20 def checked_cronjob_handler(self, *args): | 23 def checked_cronjob_handler(self, *args): |
21 assert (self.request.headers.get('X-AppEngine-Cron') or # pragma: no cover | 24 assert (self.request.headers.get('X-AppEngine-Cron') or # pragma: no cover |
22 users.is_current_user_admin()) | 25 users.is_current_user_admin()) |
23 cronjob_handler(self, *args) # pragma: no cover | 26 cronjob_handler(self, *args) # pragma: no cover |
24 return checked_cronjob_handler | 27 return checked_cronjob_handler |
25 | 28 |
26 def cross_origin_json(handler): | 29 def cross_origin_json(handler): |
30 @functools.wraps(handler) | |
27 def headered_json_handler(self, *args): | 31 def headered_json_handler(self, *args): |
28 self.response.headers.add_header("Access-Control-Allow-Origin", "*") | 32 self.response.headers.add_header("Access-Control-Allow-Origin", "*") |
29 result = handler(self, *args) | 33 result = handler(self, *args) |
30 if result is not None: | 34 if result is not None: |
31 self.response.headers.add_header('Content-Type', 'application/json') | 35 self.response.headers.add_header('Content-Type', 'application/json') |
32 self.response.write(compressed_json_dumps(result)) | 36 self.response.write(compressed_json_dumps(result)) |
33 return headered_json_handler | 37 return headered_json_handler |
34 | 38 |
35 def filter_dict(d, keys): | 39 def filter_dict(d, keys): |
36 return {key: d[key] for key in d if key in keys} | 40 return {key: d[key] for key in d if key in keys} |
37 | 41 |
38 def is_valid_user(): | 42 |
43 def get_host_permissions(kind): | |
44 """Returns compiled regex of allowed user email or True if everyone is | |
45 allowed.""" | |
46 assert kind in ('read', 'write') | |
47 if os.environ.get('SERVER_SOFTWARE', '').startswith('Development'): | |
48 host = 'Development' | |
49 else: | |
50 host = app_identity.get_default_version_hostname() | |
51 return HOST_ACLS[host][kind] | |
52 | |
53 def has_permission(kind): | |
39 if users.is_current_user_admin(): | 54 if users.is_current_user_admin(): |
55 logging.info('user is admin') | |
56 return True | |
57 email_pattern = get_host_permissions(kind) | |
58 if email_pattern is True: # Everyone. | |
Sergiy Byelozyorov
2016/07/01 17:13:06
I'd use 'everyone' rather than True. Then it's als
tandrii(chromium)
2016/07/01 18:56:55
good idea.
| |
40 return True | 59 return True |
41 user = users.get_current_user() | 60 user = users.get_current_user() |
42 return user and VALID_EMAIL_RE.match(user.email()) | 61 return user and bool(email_pattern.match(user.email())) |
62 | |
63 | |
64 def read_access(handler): | |
65 """Decorator ensuring current user has read access to this host.""" | |
66 @functools.wraps(handler) | |
67 def ensure(self, *args, **kwargs): | |
68 if not has_permission('read'): | |
69 self.redirect(users.create_login_url(self.request.url)) | |
70 return | |
71 return handler(self, *args, **kwargs) | |
72 return ensure | |
73 | |
74 | |
75 def get_friendly_hostname(): | |
76 host = app_identity.get_default_version_hostname() | |
77 return host.split('-')[0].capitalize() | |
Sergiy Byelozyorov
2016/07/01 17:13:06
Not so friendly to developers trying to understand
tandrii(chromium)
2016/07/01 18:56:55
added comment.
| |
78 | |
43 | 79 |
44 def memcachize(cache_check): | 80 def memcachize(cache_check): |
45 def decorator(f): | 81 def decorator(f): |
46 def memcachized(**kwargs): | 82 def memcachized(**kwargs): |
47 key = '%s.%s(%s)' % ( | 83 key = '%s.%s(%s)' % ( |
48 f.__module__, | 84 f.__module__, |
49 f.__name__, | 85 f.__name__, |
50 ', '.join('%s=%r' % i for i in sorted(kwargs.items())), | 86 ', '.join('%s=%r' % i for i in sorted(kwargs.items())), |
51 ) | 87 ) |
52 cache = memcache.get(key) | 88 cache = memcache.get(key) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
103 | 139 |
104 | 140 |
105 def get_full_patchset_url(codereview_hostname, issue, patchset): | 141 def get_full_patchset_url(codereview_hostname, issue, patchset): |
106 if codereview_hostname.split('.')[0].split('-')[-1] == 'review': | 142 if codereview_hostname.split('.')[0].split('-')[-1] == 'review': |
107 # This is Gerrit, which has host-review.googlesource.com. | 143 # This is Gerrit, which has host-review.googlesource.com. |
108 templ = 'https://%s/#/c/%s/%s' | 144 templ = 'https://%s/#/c/%s/%s' |
109 else: | 145 else: |
110 # Rietveld. | 146 # Rietveld. |
111 templ = 'https://%s/%s/#ps%s' | 147 templ = 'https://%s/%s/#ps%s' |
112 return templ % (codereview_hostname, issue, patchset) | 148 return templ % (codereview_hostname, issue, patchset) |
OLD | NEW |