blob: 68eb0c4c0c3806a91ef9b15b03abbd68fa118f0a [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2016 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file or at
4# https://developers.google.com/open-source/licenses/bsd
5
6"""Helper functions used by the Monorail servlet base class."""
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import calendar
12import datetime
13import logging
14import urllib
15
16from framework import framework_bizobj
17from framework import framework_helpers
18from framework import permissions
19from framework import template_helpers
20from framework import urls
21from framework import xsrf
22
23_ZERO = datetime.timedelta(0)
24
25class _UTCTimeZone(datetime.tzinfo):
26 """UTC"""
27 def utcoffset(self, _dt):
28 return _ZERO
29 def tzname(self, _dt):
30 return "UTC"
31 def dst(self, _dt):
32 return _ZERO
33
34_UTC = _UTCTimeZone()
35
36
37def GetBannerTime(timestamp):
38 """Converts a timestamp into EZT-ready data so it can appear in the banner.
39
40 Args:
41 timestamp: timestamp expressed in the following format:
42 [year,month,day,hour,minute,second]
43 e.g. [2009,3,20,21,45,50] represents March 20 2009 9:45:50 PM
44
45 Returns:
46 EZT-ready data used to display the time inside the banner message.
47 """
48 if timestamp is None:
49 return None
50
51 ts = datetime.datetime(*timestamp, tzinfo=_UTC)
52 return calendar.timegm(ts.timetuple())
53
54
55def AssertBasePermissionForUser(user, user_view):
56 """Verify user permissions and state.
57
58 Args:
59 user: user_pb2.User protocol buffer for the user
60 user_view: framework.views.UserView for the user
61 """
62 if permissions.IsBanned(user, user_view):
63 raise permissions.BannedUserException(
64 'You have been banned from using this site')
65
66
67def AssertBasePermission(mr):
68 """Make sure that the logged in user can view the requested page.
69
70 Args:
71 mr: common information parsed from the HTTP request.
72
73 Returns:
74 Nothing
75
76 Raises:
77 BannedUserException: If the user is banned.
78 PermissionException: If the user does not have permisssion to view.
79 """
80 AssertBasePermissionForUser(mr.auth.user_pb, mr.auth.user_view)
81
82 if mr.project_name and not CheckPerm(mr, permissions.VIEW):
83 logging.info('your perms are %r', mr.perms)
84 raise permissions.PermissionException(
85 'User is not allowed to view this project')
86
87
88def CheckPerm(mr, perm, art=None, granted_perms=None):
89 """Convenience method that makes permission checks easier.
90
91 Args:
92 mr: common information parsed from the HTTP request.
93 perm: A permission constant, defined in module framework.permissions
94 art: Optional artifact pb
95 granted_perms: optional set of perms granted specifically in that artifact.
96
97 Returns:
98 A boolean, whether the request can be satisfied, given the permission.
99 """
100 return mr.perms.CanUsePerm(
101 perm, mr.auth.effective_ids, mr.project,
102 permissions.GetRestrictions(art), granted_perms=granted_perms)
103
104
105def CheckPermForProject(mr, perm, project, art=None):
106 """Convenience method that makes permission checks for projects easier.
107
108 Args:
109 mr: common information parsed from the HTTP request.
110 perm: A permission constant, defined in module framework.permissions
111 project: The project to enforce permissions for.
112 art: Optional artifact pb
113
114 Returns:
115 A boolean, whether the request can be satisfied, given the permission.
116 """
117 perms = permissions.GetPermissions(
118 mr.auth.user_pb, mr.auth.effective_ids, project)
119 return perms.CanUsePerm(
120 perm, mr.auth.effective_ids, project, permissions.GetRestrictions(art))
121
122
123def ComputeIssueEntryURL(mr, config):
124 """Compute the URL to use for the "New issue" subtab.
125
126 Args:
127 mr: commonly used info parsed from the request.
128 config: ProjectIssueConfig for the current project.
129
130 Returns:
131 A URL string to use. It will be simply "entry" in the non-customized
132 case. Otherewise it will be a fully qualified URL that includes some
133 query string parameters.
134 """
135 if not config.custom_issue_entry_url:
136 return '/p/%s/issues/entry' % (mr.project_name)
137
138 base_url = config.custom_issue_entry_url
139 sep = '&' if '?' in base_url else '?'
140 token = xsrf.GenerateToken(
141 mr.auth.user_id, '/p/%s%s%s' % (mr.project_name, urls.ISSUE_ENTRY, '.do'))
142 role_name = framework_helpers.GetRoleName(mr.auth.effective_ids, mr.project)
143
144 continue_url = urllib.quote(framework_helpers.FormatAbsoluteURL(
145 mr, urls.ISSUE_ENTRY + '.do'))
146
147 return '%s%stoken=%s&role=%s&continue=%s' % (
148 base_url, sep, urllib.quote(token),
149 urllib.quote(role_name or ''), continue_url)
150
151
152def IssueListURL(mr, config, query_string=None):
153 """Make an issue list URL for non-members or members."""
154 url = '/p/%s%s' % (mr.project_name, urls.ISSUE_LIST)
155 if query_string:
156 url += '?' + query_string
157 elif framework_bizobj.UserIsInProject(mr.project, mr.auth.effective_ids):
158 if config and config.member_default_query:
159 url += '?q=' + urllib.quote_plus(config.member_default_query)
160 return url