blob: 269b89bee27402a50b8c730a042a04d08b87efd9 [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"""Protocol buffers for Monorail projects."""
7
8from __future__ import print_function
9from __future__ import division
10from __future__ import absolute_import
11
12from protorpc import messages
13
14# Project state affects permissions in that project, and project deletion.
15# It is edited on the project admin page. If it is anything other that LIVE
16# it triggers a notice at the top of every project page.
17# For more info, see the "Project deletion in Monorail" design doc.
18class ProjectState(messages.Enum):
19 """Enum for states in the project lifecycle."""
20 # Project is visible and indexed. This is the typical state.
21 #
22 # If moved_to is set, this project is live but has been moved
23 # to another location, so redirects will be used or links shown.
24 LIVE = 1
25
26 # Project owner has requested the project be archived. Project is
27 # read-only to members only, off-limits to non-members. Issues
28 # can be searched when in the project, but should not appear in
29 # site-wide searches. The project name is still in-use by this
30 # project.
31 #
32 # If a delete_time is set, then the project is doomed: (1) the
33 # state can only be changed by a site admin, and (2) the project
34 # will automatically transition to DELETABLE after that time is
35 # reached.
36 ARCHIVED = 2
37
38 # Project can be deleted at any time. The project name should
39 # have already been changed to a generated string, so it's
40 # impossible to navigate to this project, and the original name
41 # can be reused by a new project.
42 DELETABLE = 3
43
44
45# Project access affects permissions in that project.
46# It is edited on the project admin page.
47class ProjectAccess(messages.Enum):
48 """Enum for possible project access levels."""
49 # Anyone may view this project, even anonymous users.
50 ANYONE = 1
51
52 # Only project members may view the project.
53 MEMBERS_ONLY = 3
54
55
56# A Project PB represents a project in Monorail, which is a workspace for
57# project members to collaborate on issues.
58# A project is created on the project creation page, searched on the project
59# list page, and edited on the project admin page.
60# Next message: 74
61class Project(messages.Message):
62 """This protocol buffer holds all the metadata associated with a project."""
63 state = messages.EnumField(ProjectState, 1, required=True)
64 access = messages.EnumField(ProjectAccess, 18, default=ProjectAccess.ANYONE)
65
66 # The short identifier for this project. This value is lower-cased,
67 # and must be between 3 and 20 characters (inclusive). Alphanumeric
68 # and dashes are allowed, and it must start with an alpha character.
69 # Project names must be unique.
70 project_name = messages.StringField(2, required=True)
71
72 # A numeric identifier for this project.
73 project_id = messages.IntegerField(3, required=True)
74
75 # A one-line summary (human-readable) name of the project.
76 summary = messages.StringField(4, default='')
77
78 # A detailed description of the project.
79 description = messages.StringField(5, default='')
80
81 # Description of why this project has the state set as it is.
82 # This is used for administrative purposes to notify Owners that we
83 # are going to delete their project unless they can provide a good
84 # reason to not do so.
85 state_reason = messages.StringField(9)
86
87 # Time (in seconds) at which an ARCHIVED project may automatically
88 # be changed to state DELETABLE. The state change is done by a
89 # cron job.
90 delete_time = messages.IntegerField(10)
91
92 # Note that these lists are disjoint (a user ID will not appear twice).
93 owner_ids = messages.IntegerField(11, repeated=True)
94 committer_ids = messages.IntegerField(12, repeated=True)
95 contributor_ids = messages.IntegerField(15, repeated=True)
96
97 class ExtraPerms(messages.Message):
98 """Nested message for each member's extra permissions in a project."""
99 member_id = messages.IntegerField(1, required=True)
100 # Each custom perm is a single word [a-zA-Z0-9].
101 perms = messages.StringField(2, repeated=True)
102
103 extra_perms = messages.MessageField(ExtraPerms, 16, repeated=True)
104
105 # Project owners may choose to have ALL issue change notifications go to a
106 # mailing list (in addition to going directly to the users interested
107 # in that issue).
108 issue_notify_address = messages.StringField(14)
109
110 # These fields keep track of the cumulative size of all issue attachments
111 # in a given project. Normally, the number of bytes used is compared
112 # to a constant defined in the web application. However, if a custom
113 # quota is specified here, it will be used instead. An issue attachment
114 # will fail if its size would put the project over its quota. Not all
115 # projects have these fields: they are only set when the first attachment
116 # is uploaded.
117 attachment_bytes_used = messages.IntegerField(38, default=0)
118 # If quota is not set, default from tracker_constants.py is used.
119 attachment_quota = messages.IntegerField(39)
120
121 # NOTE: open slots 40, 41
122
123 # Recent_activity is a timestamp (in seconds since the Epoch) of the
124 # last time that an issue was entered, updated, or commented on.
125 recent_activity = messages.IntegerField(42, default=0)
126
127 # NOTE: open slots 43...
128
129 # Timestamp (in seconds since the Epoch) of the most recent change
130 # to this project that would invalidate cached content. It is set
131 # whenever project membership is edited, or any component config PB
132 # is edited. HTTP requests for auto-complete feeds include this
133 # value in the URL.
134 cached_content_timestamp = messages.IntegerField(53, default=0)
135
136 # If set, this project has been moved elsewhere. This can
137 # be an absolute URL, the name of another project on the same site.
138 moved_to = messages.StringField(60)
139
140 # Enable inbound email processing for issues.
141 process_inbound_email = messages.BooleanField(63, default=False)
142
143 # Limit removal of Restrict-* labels to project owners.
144 only_owners_remove_restrictions = messages.BooleanField(64, default=False)
145
146 # A per-project read-only lock. This lock (1) is meant to be
147 # long-lived (lasting as long as migration operations, project
148 # deletion, or anything else might take and (2) is meant to only
149 # limit user mutations; whether or not it limits automated actions
150 # that would change project data (such as workflow items) is
151 # determined based on the action.
152 #
153 # This lock is implemented as a user-visible string describing the
154 # reason for the project being in a read-only state. An absent or empty
155 # value indicates that the project is read-write; a present and
156 # non-empty value indicates that the project is read-only for the
157 # reason described.
158 read_only_reason = messages.StringField(65)
159
160 # This option is rarely used, but it makes sense for projects that aim for
161 # hub-and-spoke collaboration bewtween a vendor organization (like Google)
162 # and representatives of partner companies who are not supposed to know
163 # about each other.
164 # When true, it prevents project committers, contributors, and visitors
165 # from seeing the list of project members on the project summary page,
166 # on the People list page, and in autocomplete for issue owner and Cc.
167 # Project owners can always see the complete list of project members.
168 only_owners_see_contributors = messages.BooleanField(66, default=False)
169
170 # This configures the URLs generated when autolinking revision numbers.
171 # E.g., gitiles, viewvc, or crrev.com.
172 revision_url_format = messages.StringField(67)
173
174 # The home page of the Project.
175 home_page = messages.StringField(68)
176 # The url to redirect to for wiki/documentation links.
177 docs_url = messages.StringField(71)
178 # The url to redirect to for wiki/documentation links.
179 source_url = messages.StringField(72)
180 # The GCS object ID of the Project's logo.
181 logo_gcs_id = messages.StringField(69)
182 # The uploaded file name of the Project's logo.
183 logo_file_name = messages.StringField(70)
184
185 # Always send the full content of update in notifications.
186 issue_notify_always_detailed = messages.BooleanField(73, default=False)
187
188
189# This PB documents some of the duties of some of the members
190# in a given project. This info is displayed on the project People page.
191class ProjectCommitments(messages.Message):
192 project_id = messages.IntegerField(50)
193
194 class MemberCommitment(messages.Message):
195 member_id = messages.IntegerField(11, required=True)
196 notes = messages.StringField(13)
197
198 commitments = messages.MessageField(MemberCommitment, 2, repeated=True)
199
200
201def MakeProject(
202 project_name, project_id=None, state=ProjectState.LIVE,
203 access=ProjectAccess.ANYONE, summary=None, description=None,
204 moved_to=None, cached_content_timestamp=None,
205 owner_ids=None, committer_ids=None, contributor_ids=None,
206 read_only_reason=None, home_page=None, docs_url=None, source_url=None,
207 logo_gcs_id=None, logo_file_name=None):
208 """Returns a project protocol buffer with the given attributes."""
209 project = Project(
210 project_name=project_name, access=access, state=state)
211 if project_id:
212 project.project_id = project_id
213 if moved_to:
214 project.moved_to = moved_to
215 if cached_content_timestamp:
216 project.cached_content_timestamp = cached_content_timestamp
217 if summary:
218 project.summary = summary
219 if description:
220 project.description = description
221 if home_page:
222 project.home_page = home_page
223 if docs_url:
224 project.docs_url = docs_url
225 if source_url:
226 project.source_url = source_url
227 if logo_gcs_id:
228 project.logo_gcs_id = logo_gcs_id
229 if logo_file_name:
230 project.logo_file_name = logo_file_name
231
232 project.owner_ids.extend(owner_ids or [])
233 project.committer_ids.extend(committer_ids or [])
234 project.contributor_ids.extend(contributor_ids or [])
235
236 if read_only_reason is not None:
237 project.read_only_reason = read_only_reason
238
239 return project