| # Copyright 2016 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style |
| # license that can be found in the LICENSE file or at |
| # https://developers.google.com/open-source/licenses/bsd |
| |
| """Protocol buffers for Monorail projects.""" |
| |
| from __future__ import print_function |
| from __future__ import division |
| from __future__ import absolute_import |
| |
| from protorpc import messages |
| |
| # Project state affects permissions in that project, and project deletion. |
| # It is edited on the project admin page. If it is anything other that LIVE |
| # it triggers a notice at the top of every project page. |
| # For more info, see the "Project deletion in Monorail" design doc. |
| class ProjectState(messages.Enum): |
| """Enum for states in the project lifecycle.""" |
| # Project is visible and indexed. This is the typical state. |
| # |
| # If moved_to is set, this project is live but has been moved |
| # to another location, so redirects will be used or links shown. |
| LIVE = 1 |
| |
| # Project owner has requested the project be archived. Project is |
| # read-only to members only, off-limits to non-members. Issues |
| # can be searched when in the project, but should not appear in |
| # site-wide searches. The project name is still in-use by this |
| # project. |
| # |
| # If a delete_time is set, then the project is doomed: (1) the |
| # state can only be changed by a site admin, and (2) the project |
| # will automatically transition to DELETABLE after that time is |
| # reached. |
| ARCHIVED = 2 |
| |
| # Project can be deleted at any time. The project name should |
| # have already been changed to a generated string, so it's |
| # impossible to navigate to this project, and the original name |
| # can be reused by a new project. |
| DELETABLE = 3 |
| |
| |
| # Project access affects permissions in that project. |
| # It is edited on the project admin page. |
| class ProjectAccess(messages.Enum): |
| """Enum for possible project access levels.""" |
| # Anyone may view this project, even anonymous users. |
| ANYONE = 1 |
| |
| # Only project members may view the project. |
| MEMBERS_ONLY = 3 |
| |
| |
| # A Project PB represents a project in Monorail, which is a workspace for |
| # project members to collaborate on issues. |
| # A project is created on the project creation page, searched on the project |
| # list page, and edited on the project admin page. |
| # Next message: 74 |
| class Project(messages.Message): |
| """This protocol buffer holds all the metadata associated with a project.""" |
| state = messages.EnumField(ProjectState, 1, required=True) |
| access = messages.EnumField(ProjectAccess, 18, default=ProjectAccess.ANYONE) |
| |
| # The short identifier for this project. This value is lower-cased, |
| # and must be between 3 and 20 characters (inclusive). Alphanumeric |
| # and dashes are allowed, and it must start with an alpha character. |
| # Project names must be unique. |
| project_name = messages.StringField(2, required=True) |
| |
| # A numeric identifier for this project. |
| project_id = messages.IntegerField(3, required=True) |
| |
| # A one-line summary (human-readable) name of the project. |
| summary = messages.StringField(4, default='') |
| |
| # A detailed description of the project. |
| description = messages.StringField(5, default='') |
| |
| # Description of why this project has the state set as it is. |
| # This is used for administrative purposes to notify Owners that we |
| # are going to delete their project unless they can provide a good |
| # reason to not do so. |
| state_reason = messages.StringField(9) |
| |
| # Time (in seconds) at which an ARCHIVED project may automatically |
| # be changed to state DELETABLE. The state change is done by a |
| # cron job. |
| delete_time = messages.IntegerField(10) |
| |
| # Note that these lists are disjoint (a user ID will not appear twice). |
| owner_ids = messages.IntegerField(11, repeated=True) |
| committer_ids = messages.IntegerField(12, repeated=True) |
| contributor_ids = messages.IntegerField(15, repeated=True) |
| |
| class ExtraPerms(messages.Message): |
| """Nested message for each member's extra permissions in a project.""" |
| member_id = messages.IntegerField(1, required=True) |
| # Each custom perm is a single word [a-zA-Z0-9]. |
| perms = messages.StringField(2, repeated=True) |
| |
| extra_perms = messages.MessageField(ExtraPerms, 16, repeated=True) |
| |
| # Project owners may choose to have ALL issue change notifications go to a |
| # mailing list (in addition to going directly to the users interested |
| # in that issue). |
| issue_notify_address = messages.StringField(14) |
| |
| # These fields keep track of the cumulative size of all issue attachments |
| # in a given project. Normally, the number of bytes used is compared |
| # to a constant defined in the web application. However, if a custom |
| # quota is specified here, it will be used instead. An issue attachment |
| # will fail if its size would put the project over its quota. Not all |
| # projects have these fields: they are only set when the first attachment |
| # is uploaded. |
| attachment_bytes_used = messages.IntegerField(38, default=0) |
| # If quota is not set, default from tracker_constants.py is used. |
| attachment_quota = messages.IntegerField(39) |
| |
| # NOTE: open slots 40, 41 |
| |
| # Recent_activity is a timestamp (in seconds since the Epoch) of the |
| # last time that an issue was entered, updated, or commented on. |
| recent_activity = messages.IntegerField(42, default=0) |
| |
| # NOTE: open slots 43... |
| |
| # Timestamp (in seconds since the Epoch) of the most recent change |
| # to this project that would invalidate cached content. It is set |
| # whenever project membership is edited, or any component config PB |
| # is edited. HTTP requests for auto-complete feeds include this |
| # value in the URL. |
| cached_content_timestamp = messages.IntegerField(53, default=0) |
| |
| # If set, this project has been moved elsewhere. This can |
| # be an absolute URL, the name of another project on the same site. |
| moved_to = messages.StringField(60) |
| |
| # Enable inbound email processing for issues. |
| process_inbound_email = messages.BooleanField(63, default=False) |
| |
| # Limit removal of Restrict-* labels to project owners. |
| only_owners_remove_restrictions = messages.BooleanField(64, default=False) |
| |
| # A per-project read-only lock. This lock (1) is meant to be |
| # long-lived (lasting as long as migration operations, project |
| # deletion, or anything else might take and (2) is meant to only |
| # limit user mutations; whether or not it limits automated actions |
| # that would change project data (such as workflow items) is |
| # determined based on the action. |
| # |
| # This lock is implemented as a user-visible string describing the |
| # reason for the project being in a read-only state. An absent or empty |
| # value indicates that the project is read-write; a present and |
| # non-empty value indicates that the project is read-only for the |
| # reason described. |
| read_only_reason = messages.StringField(65) |
| |
| # This option is rarely used, but it makes sense for projects that aim for |
| # hub-and-spoke collaboration bewtween a vendor organization (like Google) |
| # and representatives of partner companies who are not supposed to know |
| # about each other. |
| # When true, it prevents project committers, contributors, and visitors |
| # from seeing the list of project members on the project summary page, |
| # on the People list page, and in autocomplete for issue owner and Cc. |
| # Project owners can always see the complete list of project members. |
| only_owners_see_contributors = messages.BooleanField(66, default=False) |
| |
| # This configures the URLs generated when autolinking revision numbers. |
| # E.g., gitiles, viewvc, or crrev.com. |
| revision_url_format = messages.StringField(67) |
| |
| # The home page of the Project. |
| home_page = messages.StringField(68) |
| # The url to redirect to for wiki/documentation links. |
| docs_url = messages.StringField(71) |
| # The url to redirect to for wiki/documentation links. |
| source_url = messages.StringField(72) |
| # The GCS object ID of the Project's logo. |
| logo_gcs_id = messages.StringField(69) |
| # The uploaded file name of the Project's logo. |
| logo_file_name = messages.StringField(70) |
| |
| # Always send the full content of update in notifications. |
| issue_notify_always_detailed = messages.BooleanField(73, default=False) |
| |
| |
| # This PB documents some of the duties of some of the members |
| # in a given project. This info is displayed on the project People page. |
| class ProjectCommitments(messages.Message): |
| project_id = messages.IntegerField(50) |
| |
| class MemberCommitment(messages.Message): |
| member_id = messages.IntegerField(11, required=True) |
| notes = messages.StringField(13) |
| |
| commitments = messages.MessageField(MemberCommitment, 2, repeated=True) |
| |
| |
| def MakeProject( |
| project_name, project_id=None, state=ProjectState.LIVE, |
| access=ProjectAccess.ANYONE, summary=None, description=None, |
| moved_to=None, cached_content_timestamp=None, |
| owner_ids=None, committer_ids=None, contributor_ids=None, |
| read_only_reason=None, home_page=None, docs_url=None, source_url=None, |
| logo_gcs_id=None, logo_file_name=None): |
| """Returns a project protocol buffer with the given attributes.""" |
| project = Project( |
| project_name=project_name, access=access, state=state) |
| if project_id: |
| project.project_id = project_id |
| if moved_to: |
| project.moved_to = moved_to |
| if cached_content_timestamp: |
| project.cached_content_timestamp = cached_content_timestamp |
| if summary: |
| project.summary = summary |
| if description: |
| project.description = description |
| if home_page: |
| project.home_page = home_page |
| if docs_url: |
| project.docs_url = docs_url |
| if source_url: |
| project.source_url = source_url |
| if logo_gcs_id: |
| project.logo_gcs_id = logo_gcs_id |
| if logo_file_name: |
| project.logo_file_name = logo_file_name |
| |
| project.owner_ids.extend(owner_ids or []) |
| project.committer_ids.extend(committer_ids or []) |
| project.contributor_ids.extend(contributor_ids or []) |
| |
| if read_only_reason is not None: |
| project.read_only_reason = read_only_reason |
| |
| return project |