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

Side by Side Diff: appengine/monorail/project/projectadminadvanced.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/project/projectadmin.py ('k') | appengine/monorail/project/projectexport.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 """Page and form handlers for project administration "advanced" subtab.
7
8 The advanced subtab allows the project to be archived, unarchived, deleted, or
9 marked as moved. Site admins can use this page to "doom" a project, which is
10 basically archiving it in a way that cannot be reversed by the project owners.
11
12 The page also shows project data storage quota and usage values, and
13 site admins can edit those quotas.
14 """
15
16 import logging
17 import time
18
19 from third_party import ezt
20
21 from framework import framework_constants
22 from framework import framework_helpers
23 from framework import permissions
24 from framework import servlet
25 from framework import template_helpers
26 from framework import urls
27 from proto import project_pb2
28 from tracker import tracker_constants
29
30
31 class ProjectAdminAdvanced(servlet.Servlet):
32 """A page with project state options for the Project Owner(s)."""
33
34 _PAGE_TEMPLATE = 'project/project-admin-advanced-page.ezt'
35 _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_ADMIN
36
37 def AssertBasePermission(self, mr):
38 """Make sure that the logged in user has permission to view this page.
39
40 Args:
41 mr: commonly used info parsed from the request.
42 """
43 super(ProjectAdminAdvanced, self).AssertBasePermission(mr)
44 if not self.CheckPerm(mr, permissions.EDIT_PROJECT):
45 raise permissions.PermissionException(
46 'User is not allowed to administer this project')
47
48 def GatherPageData(self, mr):
49 """Build up a dictionary of data values to use when rendering the page.
50
51 Args:
52 mr: commonly used info parsed from the request.
53
54 Returns:
55 Dict of values used by EZT for rendering the "Advanced" subtab.
56 """
57 page_data = {
58 'admin_tab_mode': self.ADMIN_TAB_ADVANCED,
59 }
60 page_data.update(self._GatherPublishingOptions(mr))
61 page_data.update(self._GatherQuotaData(mr))
62
63 return page_data
64
65 def _GatherPublishingOptions(self, mr):
66 """Gather booleans to control the publishing buttons to show in EZT."""
67 state = mr.project.state
68 offer_archive = state != project_pb2.ProjectState.ARCHIVED
69 offer_delete = state == project_pb2.ProjectState.ARCHIVED
70 offer_publish = (
71 state == project_pb2.ProjectState.ARCHIVED and
72 (self.CheckPerm(mr, permissions.PUBLISH_PROJECT) or
73 not mr.project.state_reason))
74 offer_move = state == project_pb2.ProjectState.LIVE
75 offer_doom = self.CheckPerm(mr, permissions.ADMINISTER_SITE)
76 moved_to = mr.project.moved_to or 'http://'
77
78 publishing_data = {
79 'offer_archive': ezt.boolean(offer_archive),
80 'offer_publish': ezt.boolean(offer_publish),
81 'offer_delete': ezt.boolean(offer_delete),
82 'offer_move': ezt.boolean(offer_move),
83 'moved_to': moved_to,
84 'offer_doom': ezt.boolean(offer_doom),
85 'default_doom_reason': framework_constants.DEFAULT_DOOM_REASON,
86 }
87
88 return publishing_data
89
90 def _GatherQuotaData(self, mr):
91 """Gather quota info from backends so that it can be passed to EZT."""
92 offer_quota_editing = self.CheckPerm(mr, permissions.EDIT_QUOTA)
93
94 quota_data = {
95 'offer_quota_editing': ezt.boolean(offer_quota_editing),
96 'attachment_quota': self._BuildAttachmentQuotaData(mr.project),
97 }
98
99 return quota_data
100
101 def _BuildComponentQuota(self, used_bytes, quota_bytes, field_name):
102 """Return an object to easily display quota info in EZT."""
103 if quota_bytes:
104 used_percent = 100 * used_bytes / quota_bytes
105 else:
106 used_percent = 0
107
108 quota_mb = quota_bytes / 1024 / 1024
109
110 return template_helpers.EZTItem(
111 used=template_helpers.BytesKbOrMb(used_bytes),
112 quota_mb=quota_mb,
113 used_percent=used_percent,
114 avail_percent=100 - used_percent,
115 field_name=field_name)
116
117 def _BuildAttachmentQuotaData(self, project):
118 return self._BuildComponentQuota(
119 project.attachment_bytes_used,
120 project.attachment_quota or
121 tracker_constants.ISSUE_ATTACHMENTS_QUOTA_HARD,
122 'attachment_quota_mb')
123
124 def ProcessFormData(self, mr, post_data):
125 """Process the posted form.
126
127 Args:
128 mr: commonly used info parsed from the request.
129 post_data: dictionary of HTML form data.
130
131 Returns:
132 String URL to redirect to after processing is completed.
133 """
134 if 'savechanges' in post_data:
135 self._ProcessQuota(mr, post_data)
136 else:
137 self._ProcessPublishingOptions(mr, post_data)
138
139 if 'deletebtn' in post_data:
140 url = framework_helpers.FormatAbsoluteURL(
141 mr, urls.HOSTING_HOME, include_project=False)
142 else:
143 url = framework_helpers.FormatAbsoluteURL(
144 mr, urls.ADMIN_ADVANCED, saved=1, ts=int(time.time()))
145
146 return url
147
148 def _ProcessQuota(self, mr, post_data):
149 """Process form data to update project quotas."""
150 if not self.CheckPerm(mr, permissions.EDIT_QUOTA):
151 raise permissions.PermissionException(
152 'User is not allowed to change project quotas')
153
154 try:
155 new_attachment_quota = int(post_data['attachment_quota_mb'])
156 new_attachment_quota *= 1024 * 1024
157 except ValueError:
158 mr.errors.attachment_quota = 'Invalid value'
159 self.PleaseCorrect(mr) # Don't echo back the bad input, just start over.
160 return
161
162 self.services.project.UpdateProject(
163 mr.cnxn, mr.project.project_id,
164 attachment_quota=new_attachment_quota)
165
166 def _ProcessPublishingOptions(self, mr, post_data):
167 """Process form data to update project state."""
168 # Note that EDIT_PROJECT is the base permission for this servlet, but
169 # dooming and undooming projects also requires PUBLISH_PROJECT.
170
171 state = mr.project.state
172
173 if 'archivebtn' in post_data and not mr.project.delete_time:
174 self.services.project.UpdateProject(
175 mr.cnxn, mr.project.project_id,
176 state=project_pb2.ProjectState.ARCHIVED)
177
178 elif 'deletebtn' in post_data: # Mark the project for immediate deletion.
179 if state != project_pb2.ProjectState.ARCHIVED:
180 raise permissions.PermissionException(
181 'Projects must be archived before being deleted')
182 self.services.project.MarkProjectDeletable(
183 mr.cnxn, mr.project_id, self.services.config)
184
185 elif 'doombtn' in post_data: # Go from any state to forced ARCHIVED.
186 if not self.CheckPerm(mr, permissions.PUBLISH_PROJECT):
187 raise permissions.PermissionException(
188 'User is not allowed to doom projects')
189 reason = post_data.get('reason')
190 delete_time = time.time() + framework_constants.DEFAULT_DOOM_PERIOD
191 self.services.project.UpdateProject(
192 mr.cnxn, mr.project.project_id,
193 state=project_pb2.ProjectState.ARCHIVED, state_reason=reason,
194 delete_time=delete_time)
195
196 elif 'publishbtn' in post_data: # Go from any state to LIVE
197 if (mr.project.delete_time and
198 not self.CheckPerm(mr, permissions.PUBLISH_PROJECT)):
199 raise permissions.PermissionException(
200 'User is not allowed to unarchive doomed projects')
201 self.services.project.UpdateProject(
202 mr.cnxn, mr.project.project_id,
203 state=project_pb2.ProjectState.LIVE, state_reason='', delete_time=0,
204 read_only_reason='')
205
206 elif 'movedbtn' in post_data: # Record the moved_to location.
207 if state != project_pb2.ProjectState.LIVE:
208 raise permissions.PermissionException(
209 'This project is not live, no user can move it')
210 moved_to = post_data.get('moved_to', '')
211 self.services.project.UpdateProject(
212 mr.cnxn, mr.project.project_id, moved_to=moved_to)
OLDNEW
« no previous file with comments | « appengine/monorail/project/projectadmin.py ('k') | appengine/monorail/project/projectexport.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698