Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: appengine/monorail/search/backendnonviewable.py

Issue 1868553004: Open Source Monorail (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « appengine/monorail/search/ast2sort.py ('k') | appengine/monorail/search/backendsearch.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is govered 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 """Servlet that searches for issues that the specified user cannot view.
7
8 The GET request to a backend has query string parameters for the
9 shard_id, a user_id, and list of project IDs. It returns a
10 JSON-formatted dict with issue_ids that that user is not allowed to
11 view. As a side-effect, this servlet updates multiple entries
12 in memcache, including each "nonviewable:USER_ID;PROJECT_ID;SHARD_ID".
13 """
14
15 import logging
16
17 from google.appengine.api import memcache
18
19 from framework import framework_constants
20 from framework import framework_helpers
21 from framework import jsonfeed
22 from framework import permissions
23 from framework import sql
24
25
26 RESTRICT_VIEW_PATTERN = 'restrict-view-%'
27
28 # We cache the set of IIDs that a given user cannot view, and we invalidate
29 # that set when the issues are changed via Monorail. Also, we limit the live
30 # those cache entries so that changes in a user's (direct or indirect) roles
31 # in a project will take effect.
32 NONVIEWABLE_MEMCACHE_EXPIRATION = 15 * framework_constants.SECS_PER_MINUTE
33
34
35 class BackendNonviewable(jsonfeed.InternalTask):
36 """JSON servlet for getting issue IDs that the specified user cannot view."""
37
38 CHECK_SAME_APP = True
39
40 def HandleRequest(self, mr):
41 """Get all the user IDs that the specified user cannot view.
42
43 Args:
44 mr: common information parsed from the HTTP request.
45
46 Returns:
47 Results dictionary {project_id: [issue_id]} in JSON format.
48 """
49 if mr.shard_id is None:
50 return {'message': 'Cannot proceed without a valid shard_id.'}
51 user_id = mr.specified_logged_in_user_id
52 user = self.services.user.GetUser(mr.cnxn, user_id)
53 effective_ids = self.services.usergroup.LookupMemberships(mr.cnxn, user_id)
54 if user_id:
55 effective_ids.add(user_id)
56 project_id = mr.specified_project_id
57 project = self.services.project.GetProject(mr.cnxn, project_id)
58
59 perms = permissions.GetPermissions(user, effective_ids, project)
60
61 nonviewable_iids = self.GetNonviewableIIDs(
62 mr.cnxn, user, effective_ids, project, perms, mr.shard_id)
63
64 cached_ts = mr.invalidation_timestep
65 if mr.specified_project_id:
66 memcache.set(
67 'nonviewable:%d;%d;%d' % (project_id, user_id, mr.shard_id),
68 (nonviewable_iids, cached_ts),
69 time=NONVIEWABLE_MEMCACHE_EXPIRATION)
70 else:
71 memcache.set(
72 'nonviewable:all;%d;%d' % (user_id, mr.shard_id),
73 (nonviewable_iids, cached_ts),
74 time=NONVIEWABLE_MEMCACHE_EXPIRATION)
75
76 logging.info('set nonviewable:%s;%d;%d to %r', project_id, user_id,
77 mr.shard_id, nonviewable_iids)
78
79 return {
80 'nonviewable': nonviewable_iids,
81
82 # These are not used in the frontend, but useful for debugging.
83 'project_id': project_id,
84 'user_id': user_id,
85 'shard_id': mr.shard_id,
86 }
87
88 def GetNonviewableIIDs(
89 self, cnxn, user, effective_ids, project, perms, shard_id):
90 """Return a list of IIDs that the user cannot view in the project shard."""
91 # Project owners and site admins can see all issues.
92 if not perms.consider_restrictions:
93 return []
94
95 # There are two main parts to the computation that we do in parallel:
96 # getting at-risk IIDs and getting OK-iids.
97 cnxn_2 = sql.MonorailConnection()
98 at_risk_iids_promise = framework_helpers.Promise(
99 self.GetAtRiskIIDs, cnxn_2, user, effective_ids, project, perms, shard_id)
100 ok_iids = self.GetViewableIIDs(
101 cnxn, effective_ids, project.project_id, shard_id)
102 at_risk_iids = at_risk_iids_promise.WaitAndGetValue()
103
104 # The set of non-viewable issues is the at-risk ones minus the ones where
105 # the user is the reporter, owner, CC'd, or granted "View" permission.
106 nonviewable_iids = set(at_risk_iids).difference(ok_iids)
107
108 return list(nonviewable_iids)
109
110 def GetAtRiskIIDs(
111 self, cnxn, user, effective_ids, project, perms, shard_id):
112 """Return IIDs of restricted issues that user might not be able to view."""
113 at_risk_label_ids = self.GetPersonalAtRiskLabelIDs(
114 cnxn, user, effective_ids, project, perms)
115 at_risk_iids = self.services.issue.GetIIDsByLabelIDs(
116 cnxn, at_risk_label_ids, project.project_id, shard_id)
117
118 return at_risk_iids
119
120 def GetPersonalAtRiskLabelIDs(
121 self, cnxn, _user, effective_ids, project, perms):
122 """Return list of label_ids for restriction labels that user can't view."""
123 at_risk_label_ids = []
124 label_def_rows = self.services.config.GetLabelDefRowsAnyProject(
125 cnxn, where=[('LOWER(label) LIKE %s', [RESTRICT_VIEW_PATTERN])])
126 for label_id, _pid, _rank, label, _docstring, _hidden in label_def_rows:
127 label_lower = label.lower()
128 needed_perm = label_lower.split('-', 2)[-1]
129 if not perms.CanUsePerm(needed_perm, effective_ids, project, []):
130 at_risk_label_ids.append(label_id)
131
132 return at_risk_label_ids
133
134 def GetViewableIIDs(self, cnxn, effective_ids, project_id, shard_id):
135 """Return IIDs of issues that user can view because they participate."""
136 # Anon user is never reporter, owner, CC'd or granted perms.
137 if not effective_ids:
138 return []
139
140 ok_iids = self.services.issue.GetIIDsByParticipant(
141 cnxn, effective_ids, [project_id], shard_id)
142
143 return ok_iids
OLDNEW
« no previous file with comments | « appengine/monorail/search/ast2sort.py ('k') | appengine/monorail/search/backendsearch.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698