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

Side by Side Diff: appengine/monorail/tracker/componentcreate.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
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 """A servlet for project owners to create a new component def."""
7
8 import logging
9 import time
10
11 from framework import framework_helpers
12 from framework import framework_views
13 from framework import jsonfeed
14 from framework import permissions
15 from framework import servlet
16 from framework import urls
17 from tracker import component_helpers
18 from tracker import tracker_bizobj
19 from tracker import tracker_constants
20 from tracker import tracker_views
21
22 from third_party import ezt
23
24
25 class ComponentCreate(servlet.Servlet):
26 """Servlet allowing project owners to create a component."""
27
28 _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_PROCESS
29 _PAGE_TEMPLATE = 'tracker/component-create-page.ezt'
30
31 def AssertBasePermission(self, mr):
32 """Check whether the user has any permission to visit this page.
33
34 Args:
35 mr: commonly used info parsed from the request.
36 """
37 super(ComponentCreate, self).AssertBasePermission(mr)
38 if not self.CheckPerm(mr, permissions.EDIT_PROJECT):
39 raise permissions.PermissionException(
40 'User is not allowed to administer this project')
41
42 def GatherPageData(self, mr):
43 """Build up a dictionary of data values to use when rendering the page.
44
45 Args:
46 mr: commonly used info parsed from the request.
47
48 Returns:
49 Dict of values used by EZT for rendering the page.
50 """
51 config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
52 users_by_id = framework_views.MakeAllUserViews(
53 mr.cnxn, self.services.user,
54 *[list(cd.admin_ids) + list(cd.cc_ids)
55 for cd in config.component_defs])
56 component_def_views = [
57 tracker_views.ComponentDefView(cd, users_by_id)
58 # TODO(jrobbins): future component-level view restrictions.
59 for cd in config.component_defs]
60 for cdv in component_def_views:
61 setattr(cdv, 'selected', None)
62 path = (cdv.parent_path + '>' + cdv.leaf_name).lstrip('>')
63 if path == mr.component_path:
64 setattr(cdv, 'selected', True)
65
66 return {
67 'parent_path': mr.component_path,
68 'admin_tab_mode': servlet.Servlet.PROCESS_TAB_COMPONENTS,
69 'component_defs': component_def_views,
70 'initial_leaf_name': '',
71 'initial_docstring': '',
72 'initial_deprecated': ezt.boolean(False),
73 'initial_admins': [],
74 'initial_cc': [],
75 }
76
77 def ProcessFormData(self, mr, post_data):
78 """Validate and store the contents of the issues tracker admin page.
79
80 Args:
81 mr: commonly used info parsed from the request.
82 post_data: HTML form data from the request.
83
84 Returns:
85 String URL to redirect the user to, or None if response was already sent.
86 """
87 config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
88 parent_path = post_data.get('parent_path', '')
89 parsed = component_helpers.ParseComponentRequest(
90 mr, post_data, self.services.user)
91
92 if parent_path:
93 parent_def = tracker_bizobj.FindComponentDef(parent_path, config)
94 if not parent_def:
95 self.abort(500, 'parent component not found')
96 allow_parent_edit = permissions.CanEditComponentDef(
97 mr.auth.effective_ids, mr.perms, mr.project, parent_def, config)
98 if not allow_parent_edit:
99 raise permissions.PermissionException(
100 'User is not allowed to add a subcomponent here')
101
102 path = '%s>%s' % (parent_path, parsed.leaf_name)
103 else:
104 path = parsed.leaf_name
105
106 leaf_name_error_msg = LeafNameErrorMessage(
107 parent_path, parsed.leaf_name, config)
108 if leaf_name_error_msg:
109 mr.errors.leaf_name = leaf_name_error_msg
110
111 if mr.errors.AnyErrors():
112 self.PleaseCorrect(
113 mr, parent_path=parent_path,
114 initial_leaf_name=parsed.leaf_name,
115 initial_docstring=parsed.docstring,
116 initial_deprecated=ezt.boolean(parsed.deprecated),
117 initial_admins=parsed.admin_usernames,
118 initial_cc=parsed.cc_usernames,
119 )
120 return
121
122 created = int(time.time())
123 creator_id = self.services.user.LookupUserID(
124 mr.cnxn, mr.auth.email, autocreate=False)
125
126 self.services.config.CreateComponentDef(
127 mr.cnxn, mr.project_id, path, parsed.docstring, parsed.deprecated,
128 parsed.admin_ids, parsed.cc_ids, created, creator_id)
129
130 return framework_helpers.FormatAbsoluteURL(
131 mr, urls.ADMIN_COMPONENTS, saved=1, ts=int(time.time()))
132
133
134 class CheckComponentNameJSON(jsonfeed.JsonFeed):
135 """JSON data for handling name checks when creating a component."""
136
137 def HandleRequest(self, mr):
138 """Provide the UI with info about the availability of the component name.
139
140 Args:
141 mr: common information parsed from the HTTP request.
142
143 Returns:
144 Results dictionary in JSON format.
145 """
146 parent_path = mr.GetParam('parent_path')
147 leaf_name = mr.GetParam('leaf_name')
148 config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
149 message = LeafNameErrorMessage(parent_path, leaf_name, config)
150
151 return {
152 'error_message': message,
153 }
154
155
156 def LeafNameErrorMessage(parent_path, leaf_name, config):
157 """Return an error message for the given component name, or None."""
158 if not tracker_constants.COMPONENT_NAME_RE.match(leaf_name):
159 return 'Invalid component name'
160
161 if parent_path:
162 path = '%s>%s' % (parent_path, leaf_name)
163 else:
164 path = leaf_name
165
166 if tracker_bizobj.FindComponentDef(path, config):
167 return 'That name is already in use.'
168
169 return None
OLDNEW
« no previous file with comments | « appengine/monorail/tracker/component_helpers.py ('k') | appengine/monorail/tracker/componentdetail.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698