# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""API service.

To manually test this API locally, use the following steps:
1. Start the development server via 'make serve'.
2. Start a new Chrome session via the command-line:
  PATH_TO_CHROME --user-data-dir=/tmp/test \
  --unsafely-treat-insecure-origin-as-secure=http://localhost:8080
3. Visit http://localhost:8080/_ah/api/explorer
4. Click shield icon in the omnibar and allow unsafe scripts.
5. Click on the "Services" menu item in the API Explorer.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import calendar
import datetime
import endpoints
import functools
import logging
import re
import time
from google.appengine.api import oauth
from protorpc import message_types
from protorpc import protojson
from protorpc import remote

import settings
from businesslogic import work_env
from features import filterrules_helpers
from features import send_notifications
from framework import authdata
from framework import exceptions
from framework import framework_constants
from framework import framework_helpers
from framework import framework_views
from framework import monitoring
from framework import monorailrequest
from framework import permissions
from framework import ratelimiter
from framework import sql
from project import project_helpers
from mrproto import api_pb2_v1
from mrproto import project_pb2
from mrproto import tracker_pb2
from search import frontendsearchpipeline
from services import api_pb2_v1_helpers
from services import client_config_svc
from services import service_manager
from services import tracker_fulltext
from sitewide import sitewide_helpers
from tracker import field_helpers
from tracker import issuedetailezt
from tracker import tracker_bizobj
from tracker import tracker_constants
from tracker import tracker_helpers
from redirect import redirect_utils

from infra_libs import ts_mon


ENDPOINTS_API_NAME = 'monorail'
DOC_URL = (
    'https://chromium.googlesource.com/infra/infra/+/main/'
    'appengine/monorail/doc/api.md')


def monorail_api_method(
    request_message, response_message, **kwargs):
  """Extends endpoints.method by performing base checks."""
  time_fn = kwargs.pop('time_fn', time.time)
  method_name = kwargs.get('name', '')
  method_path = kwargs.get('path', '')
  http_method = kwargs.get('http_method', '')
  def new_decorator(func):
    @endpoints.method(request_message, response_message, **kwargs)
    @functools.wraps(func)
    def wrapper(self, *args, **kwargs):
      start_time = time_fn()
      approximate_http_status = 200
      request = args[0]
      ret = None
      c_id = None
      c_email = None
      mar = None
      try:
        if settings.read_only and http_method.lower() != 'get':
          raise permissions.PermissionException(
              'This request is not allowed in read-only mode')
        requester = endpoints.get_current_user()
        logging.info('requester is %r', requester)
        logging.info('args is %r', args)
        logging.info('kwargs is %r', kwargs)
        auth_client_ids, auth_emails = (
            client_config_svc.GetClientConfigSvc().GetClientIDEmails())
        if settings.local_mode:
          auth_client_ids.append(endpoints.API_EXPLORER_CLIENT_ID)
        if self._services is None:
          self._set_services(service_manager.set_up_services())
        cnxn = sql.MonorailConnection()
        c_id, c_email = api_base_checks(
            request, requester, self._services, cnxn,
            auth_client_ids, auth_emails)
        mar = self.mar_factory(request, cnxn)
        self.ratelimiter.CheckStart(c_id, c_email, start_time)
        monitoring.IncrementAPIRequestsCount(
            'endpoints', c_id, client_email=c_email, handler=method_name)
        ret = func(self, mar, *args, **kwargs)
      except exceptions.NoSuchUserException as e:
        approximate_http_status = 404
        raise endpoints.NotFoundException(
            'The user does not exist: %s' % str(e))
      except (exceptions.NoSuchProjectException,
              exceptions.NoSuchIssueException,
              exceptions.NoSuchComponentException) as e:
        approximate_http_status = 404
        raise endpoints.NotFoundException(str(e))
      except (permissions.BannedUserException,
              permissions.PermissionException) as e:
        approximate_http_status = 403
        logging.info('Allowlist ID %r email %r', auth_client_ids, auth_emails)
        raise endpoints.ForbiddenException(str(e))
      except endpoints.BadRequestException:
        approximate_http_status = 400
        raise
      except endpoints.UnauthorizedException:
        approximate_http_status = 401
        # Client will refresh token and retry.
        raise
      except oauth.InvalidOAuthTokenError:
        approximate_http_status = 401
        # Client will refresh token and retry.
        raise endpoints.UnauthorizedException(
            'Auth error: InvalidOAuthTokenError')
      except (exceptions.GroupExistsException,
              exceptions.InvalidComponentNameException,
              ratelimiter.ApiRateLimitExceeded) as e:
        approximate_http_status = 400
        raise endpoints.BadRequestException(str(e))
      except Exception as e:
        approximate_http_status = 500
        logging.exception('Unexpected error in monorail API')
        raise
      finally:
        if mar:
          mar.CleanUp()
        now = time_fn()
        if c_id and c_email:
          self.ratelimiter.CheckEnd(c_id, c_email, now, start_time)
        _RecordMonitoringStats(
            start_time, request, ret, (method_name or func.__name__),
            (method_path or func.__name__), approximate_http_status, now)

      return ret

    return wrapper
  return new_decorator


def _RecordMonitoringStats(
    start_time,
    request,
    response,
    method_name,
    method_path,
    approximate_http_status,
    now=None):
  now = now or time.time()
  elapsed_ms = int((now - start_time) * 1000)
  # Use the api name, not the request path, to prevent an explosion in
  # possible field values.
  method_identifier = (
      ENDPOINTS_API_NAME + '.endpoints.' + method_name + '/' + method_path)

  # Endpoints APIs don't return the full set of http status values.
  fields = monitoring.GetCommonFields(
      approximate_http_status, method_identifier)

  monitoring.AddServerDurations(elapsed_ms, fields)
  monitoring.IncrementServerResponseStatusCount(fields)
  request_length = len(protojson.encode_message(request))
  monitoring.AddServerRequesteBytes(request_length, fields)
  response_length = 0
  if response:
    response_length = len(protojson.encode_message(response))
  monitoring.AddServerResponseBytes(response_length, fields)


def _is_requester_in_allowed_domains(requester):
  if requester.email().endswith(settings.api_allowed_email_domains):
    if framework_constants.MONORAIL_SCOPE in oauth.get_authorized_scopes(
        framework_constants.MONORAIL_SCOPE):
      return True
    else:
      logging.info("User is not authenticated with monorail scope")
  return False

def api_base_checks(request, requester, services, cnxn,
                    auth_client_ids, auth_emails):
  """Base checks for API users.

  Args:
    request: The HTTP request from Cloud Endpoints.
    requester: The user who sends the request.
    services: Services object.
    cnxn: connection to the SQL database.
    auth_client_ids: authorized client ids.
    auth_emails: authorized emails when client is anonymous.

  Returns:
    Client ID and client email.

  Raises:
    endpoints.UnauthorizedException: If the requester is anonymous.
    exceptions.NoSuchUserException: If the requester does not exist in Monorail.
    NoSuchProjectException: If the project does not exist in Monorail.
    permissions.BannedUserException: If the requester is banned.
    permissions.PermissionException: If the requester does not have
        permisssion to view.
  """
  valid_user = False
  auth_err = ''
  client_id = None

  try:
    client_id = oauth.get_client_id(framework_constants.OAUTH_SCOPE)
    logging.info('Oauth client ID %s', client_id)
  except oauth.Error as ex:
    auth_err = 'oauth.Error: %s' % ex

  if not requester:
    try:
      requester = oauth.get_current_user(framework_constants.OAUTH_SCOPE)
      logging.info('Oauth requester %s', requester.email())
    except oauth.Error as ex:
      logging.info('Got oauth error: %r', ex)
      auth_err = 'oauth.Error: %s' % ex

  if client_id and requester:
    if client_id in auth_client_ids:
      # A allowlisted client app can make requests for any user or anon.
      logging.info('Client ID %r is allowlisted', client_id)
      valid_user = True
    elif requester.email() in auth_emails:
      # A allowlisted user account can make requests via any client app.
      logging.info('Client email %r is allowlisted', requester.email())
      valid_user = True
    elif _is_requester_in_allowed_domains(requester):
      # A user with an allowed-domain email and authenticated with the
      # monorail scope is allowed to make requests via any client app.
      logging.info(
          'User email %r is within the allowed domains', requester.email())
      valid_user = True
    else:
      auth_err = (
          'Neither client ID %r nor email %r is allowlisted' %
          (client_id, requester.email()))

  if not valid_user:
    raise endpoints.UnauthorizedException('Auth error: %s' % auth_err)
  else:
    logging.info('API request from user %s:%s', client_id, requester.email())

  project_name = None
  if hasattr(request, 'projectId'):
    project_name = request.projectId
  issue_local_id = None
  if hasattr(request, 'issueId'):
    issue_local_id = request.issueId
  # This could raise exceptions.NoSuchUserException
  requester_id = services.user.LookupUserID(cnxn, requester.email())
  auth = authdata.AuthData.FromUserID(cnxn, requester_id, services)
  if permissions.IsBanned(auth.user_pb, auth.user_view):
    raise permissions.BannedUserException(
        'The user %s has been banned from using Monorail' %
        requester.email())
  if project_name:
    project = services.project.GetProjectByName(
        cnxn, project_name)
    if not project:
      raise exceptions.NoSuchProjectException(
          'Project %s does not exist' % project_name)
    # Allow to view non-live projects that were migrated.
    if (project.state != project_pb2.ProjectState.LIVE and
        project_name not in redirect_utils.PROJECT_REDIRECT_MAP):
      raise permissions.PermissionException(
          'API may not access project %s because it is not live'
          % project_name)
    if not permissions.UserCanViewProject(
        auth.user_pb, auth.effective_ids, project):
      raise permissions.PermissionException(
          'The user %s has no permission for project %s' %
          (requester.email(), project_name))
    if issue_local_id:
      # This may raise a NoSuchIssueException.
      issue = services.issue.GetIssueByLocalID(
          cnxn, project.project_id, issue_local_id)
      perms = permissions.GetPermissions(
          auth.user_pb, auth.effective_ids, project)
      config = services.config.GetProjectConfig(cnxn, project.project_id)
      granted_perms = tracker_bizobj.GetGrantedPerms(
          issue, auth.effective_ids, config)
      if not permissions.CanViewIssue(
          auth.effective_ids, perms, project, issue,
          granted_perms=granted_perms):
        raise permissions.PermissionException(
            'User is not allowed to view this issue %s:%d' %
            (project_name, issue_local_id))

  return client_id, requester.email()


@endpoints.api(name=ENDPOINTS_API_NAME, version='v1',
               description='Monorail API to manage issues.',
               allowed_client_ids=endpoints.SKIP_CLIENT_ID_CHECK,
               documentation=DOC_URL)
class MonorailApi(remote.Service):

  # Class variables. Handy to mock.
  _services = None
  _mar = None

  ratelimiter = ratelimiter.ApiRateLimiter()

  @classmethod
  def _set_services(cls, services):
    cls._services = services

  def mar_factory(self, request, cnxn):
    if not self._mar:
      self._mar = monorailrequest.MonorailApiRequest(
          request, self._services, cnxn=cnxn)
    return self._mar

  def aux_delete_comment(self, mar, request, delete=True):
    action_name = 'delete' if delete else 'undelete'

    with work_env.WorkEnv(mar, self._services) as we:
      issue = we.GetIssueByLocalID(
          mar.project_id, request.issueId, use_cache=False)
      all_comments = we.ListIssueComments(issue)
      try:
        issue_comment = all_comments[request.commentId]
      except IndexError:
        raise exceptions.NoSuchIssueException(
              'The issue %s:%d does not have comment %d.' %
              (mar.project_name, request.issueId, request.commentId))

      issue_perms = permissions.UpdateIssuePermissions(
          mar.perms, mar.project, issue, mar.auth.effective_ids,
          granted_perms=mar.granted_perms)
      commenter = we.GetUser(issue_comment.user_id)

      if not permissions.CanDeleteComment(
          issue_comment, commenter, mar.auth.user_id, issue_perms):
        raise permissions.PermissionException(
              'User is not allowed to %s the comment %d of issue %s:%d' %
              (action_name, request.commentId, mar.project_name,
               request.issueId))

      we.DeleteComment(issue, issue_comment, delete=delete)
    return api_pb2_v1.IssuesCommentsDeleteResponse()

  @monorail_api_method(
      api_pb2_v1.ISSUES_COMMENTS_DELETE_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.IssuesCommentsDeleteResponse,
      path='projects/{projectId}/issues/{issueId}/comments/{commentId}',
      http_method='DELETE',
      name='issues.comments.delete')
  def issues_comments_delete(self, mar, request):
    """Delete a comment."""
    return self.aux_delete_comment(mar, request, True)

  def parse_imported_reporter(self, mar, request):
    """Handle the case where an API client is importing issues for users.

    Args:
      mar: monorail API request object including auth and perms.
      request: A request PB that defines author and published fields.

    Returns:
      A pair (reporter_id, timestamp) with the user ID of the user to
      attribute the comment to and timestamp of the original comment.
      If the author field is not set, this is not an import request
      and the comment is attributed to the API client as per normal.
      An API client that is attempting to post on behalf of other
      users must have the ImportComment permission in the current
      project.
    """
    reporter_id = mar.auth.user_id
    timestamp = None
    if (request.author and request.author.name and
        request.author.name != mar.auth.email):
      if not mar.perms.HasPerm(
          permissions.IMPORT_COMMENT, mar.auth.user_id, mar.project):
        logging.info('name is %r', request.author.name)
        raise permissions.PermissionException(
            'User is not allowed to attribue comments to others')
      reporter_id = self._services.user.LookupUserID(
              mar.cnxn, request.author.name, autocreate=True)
      logging.info('Importing issue or comment.')
      if request.published:
        timestamp = calendar.timegm(request.published.utctimetuple())

    return reporter_id, timestamp

  @monorail_api_method(
      api_pb2_v1.ISSUES_COMMENTS_INSERT_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.IssuesCommentsInsertResponse,
      path='projects/{projectId}/issues/{issueId}/comments',
      http_method='POST',
      name='issues.comments.insert')
  def issues_comments_insert(self, mar, request):
    # type (...) -> mrproto.api_pb2_v1.IssuesCommentsInsertResponse
    """Add a comment."""
    # Because we will modify issues, load from DB rather than cache.
    issue = self._services.issue.GetIssueByLocalID(
        mar.cnxn, mar.project_id, request.issueId, use_cache=False)
    old_owner_id = tracker_bizobj.GetOwnerId(issue)
    if not permissions.CanCommentIssue(
        mar.auth.effective_ids, mar.perms, mar.project, issue,
        mar.granted_perms):
      raise permissions.PermissionException(
          'User is not allowed to comment this issue (%s, %d)' %
          (request.projectId, request.issueId))

    # Temporary block on updating approval subfields.
    if request.updates and request.updates.fieldValues:
      fds_by_name = {fd.field_name.lower(): fd for fd in mar.config.field_defs}
      for fv in request.updates.fieldValues:
        # Checking for fv.approvalName is unreliable since it can be removed.
        fd = fds_by_name.get(fv.fieldName.lower())
        if fd and fd.approval_id:
          raise exceptions.ActionNotSupported(
              'No API support for approval field changes: (approval %s owns %s)'
              % (fd.approval_id, fd.field_name))
        # if fd was None, that gets dealt with later.

    if request.content and len(
        request.content) > tracker_constants.MAX_COMMENT_CHARS:
      raise endpoints.BadRequestException(
          'Comment is too long on this issue (%s, %d' %
          (request.projectId, request.issueId))

    updates_dict = {}
    move_to_project = None
    if request.updates:
      if not permissions.CanEditIssue(
          mar.auth.effective_ids, mar.perms, mar.project, issue,
          mar.granted_perms):
        raise permissions.PermissionException(
            'User is not allowed to edit this issue (%s, %d)' %
            (request.projectId, request.issueId))
      if request.updates.moveToProject:
        move_to = request.updates.moveToProject.lower()
        move_to_project = issuedetailezt.CheckMoveIssueRequest(
            self._services, mar, issue, True, move_to, mar.errors)
        if mar.errors.AnyErrors():
          raise endpoints.BadRequestException(mar.errors.move_to)

      updates_dict['summary'] = request.updates.summary
      updates_dict['status'] = request.updates.status
      updates_dict['is_description'] = request.updates.is_description
      if request.updates.owner:
        # A current issue owner can be removed via the API with a
        # NO_USER_NAME('----') input.
        if request.updates.owner == framework_constants.NO_USER_NAME:
          updates_dict['owner'] = framework_constants.NO_USER_SPECIFIED
        else:
          new_owner_id = self._services.user.LookupUserID(
              mar.cnxn, request.updates.owner)
          valid, msg = tracker_helpers.IsValidIssueOwner(
              mar.cnxn, mar.project, new_owner_id, self._services)
          if not valid:
            raise endpoints.BadRequestException(msg)
          updates_dict['owner'] = new_owner_id
      updates_dict['cc_add'], updates_dict['cc_remove'] = (
          api_pb2_v1_helpers.split_remove_add(request.updates.cc))
      updates_dict['cc_add'] = list(self._services.user.LookupUserIDs(
          mar.cnxn, updates_dict['cc_add'], autocreate=True).values())
      updates_dict['cc_remove'] = list(self._services.user.LookupUserIDs(
          mar.cnxn, updates_dict['cc_remove']).values())
      updates_dict['labels_add'], updates_dict['labels_remove'] = (
          api_pb2_v1_helpers.split_remove_add(request.updates.labels))

      field_helpers.ValidateLabels(
          mar.cnxn,
          self._services,
          mar.project_id,
          updates_dict.get('labels_add', []),
          ezt_errors=mar.errors)
      if mar.errors.AnyErrors():
        raise endpoints.BadRequestException(
            'Invalid field values: %s' % mar.errors.labels)

      blocked_on_add_strs, blocked_on_remove_strs = (
          api_pb2_v1_helpers.split_remove_add(request.updates.blockedOn))
      blocking_add_strs, blocking_remove_strs = (
          api_pb2_v1_helpers.split_remove_add(request.updates.blocking))
      blocked_on_add_iids = api_pb2_v1_helpers.issue_global_ids(
          blocked_on_add_strs, issue.project_id, mar, self._services)
      blocked_on_remove_iids = api_pb2_v1_helpers.issue_global_ids(
          blocked_on_remove_strs, issue.project_id, mar, self._services)
      blocking_add_iids = api_pb2_v1_helpers.issue_global_ids(
          blocking_add_strs, issue.project_id, mar, self._services)
      blocking_remove_iids = api_pb2_v1_helpers.issue_global_ids(
          blocking_remove_strs, issue.project_id, mar, self._services)
      all_block = (
          blocked_on_add_iids + blocked_on_remove_iids + blocking_add_iids +
          blocking_remove_iids)
      for iid in all_block:
        # Because we will modify issues, load from DB rather than cache.
        issue = self._services.issue.GetIssue(mar.cnxn, iid, use_cache=False)
        project = self._services.project.GetProjectByName(
            mar.cnxn, issue.project_name)
        if not tracker_helpers.CanEditProjectIssue(mar, project, issue,
                                                   mar.granted_perms):
          raise permissions.PermissionException(
              'User is not allowed to block with issue (%s, %d)' %
              (issue.project_name, issue.local_id))
      updates_dict['blocked_on_add'] = blocked_on_add_iids
      updates_dict['blocked_on_remove'] = blocked_on_remove_iids
      updates_dict['blocking_add'] = blocking_add_iids
      updates_dict['blocking_remove'] = blocking_remove_iids
      components_add_strs, components_remove_strs = (
          api_pb2_v1_helpers.split_remove_add(request.updates.components))
      updates_dict['components_add'] = (
          api_pb2_v1_helpers.convert_component_ids(
              mar.config, components_add_strs))
      updates_dict['components_remove'] = (
          api_pb2_v1_helpers.convert_component_ids(
              mar.config, components_remove_strs))
      if request.updates.mergedInto:
        merge_project_name, merge_local_id = tracker_bizobj.ParseIssueRef(
            request.updates.mergedInto)
        merge_into_project = self._services.project.GetProjectByName(
            mar.cnxn, merge_project_name or issue.project_name)
        # Because we will modify issues, load from DB rather than cache.
        merge_into_issue = self._services.issue.GetIssueByLocalID(
            mar.cnxn, merge_into_project.project_id, merge_local_id,
            use_cache=False)
        if not tracker_helpers.CanEditProjectIssue(
            mar, merge_into_project, merge_into_issue, mar.granted_perms):
          raise permissions.PermissionException(
              'User is not allowed to merge into issue %s:%s' %
              (merge_into_issue.project_name, merge_into_issue.local_id))
        updates_dict['merged_into'] = merge_into_issue.issue_id
      (updates_dict['field_vals_add'], updates_dict['field_vals_remove'],
       updates_dict['fields_clear'], updates_dict['fields_labels_add'],
       updates_dict['fields_labels_remove']) = (
          api_pb2_v1_helpers.convert_field_values(
              request.updates.fieldValues, mar, self._services))

    field_helpers.ValidateCustomFields(
        mar.cnxn, self._services,
        (updates_dict.get('field_vals_add', []) +
         updates_dict.get('field_vals_remove', [])),
        mar.config, mar.project, ezt_errors=mar.errors)
    if mar.errors.AnyErrors():
      raise endpoints.BadRequestException(
          'Invalid field values: %s' % mar.errors.custom_fields)

    updates_dict['labels_add'] = (
        updates_dict.get('labels_add', []) +
        updates_dict.get('fields_labels_add', []))
    updates_dict['labels_remove'] = (
        updates_dict.get('labels_remove', []) +
        updates_dict.get('fields_labels_remove', []))

    # TODO(jrobbins): Stop using updates_dict in the first place.
    delta = tracker_bizobj.MakeIssueDelta(
        updates_dict.get('status'),
        updates_dict.get('owner'),
        updates_dict.get('cc_add', []),
        updates_dict.get('cc_remove', []),
        updates_dict.get('components_add', []),
        updates_dict.get('components_remove', []),
        (updates_dict.get('labels_add', []) +
         updates_dict.get('fields_labels_add', [])),
        (updates_dict.get('labels_remove', []) +
         updates_dict.get('fields_labels_remove', [])),
        updates_dict.get('field_vals_add', []),
        updates_dict.get('field_vals_remove', []),
        updates_dict.get('fields_clear', []),
        updates_dict.get('blocked_on_add', []),
        updates_dict.get('blocked_on_remove', []),
        updates_dict.get('blocking_add', []),
        updates_dict.get('blocking_remove', []),
        updates_dict.get('merged_into'),
        updates_dict.get('summary'))

    importer_id = None
    reporter_id, timestamp = self.parse_imported_reporter(mar, request)
    if reporter_id != mar.auth.user_id:
      importer_id = mar.auth.user_id

    # TODO(jrobbins): Finish refactoring to make everything go through work_env.
    _, comment = self._services.issue.DeltaUpdateIssue(
        cnxn=mar.cnxn, services=self._services,
        reporter_id=reporter_id, project_id=mar.project_id, config=mar.config,
        issue=issue, delta=delta, index_now=False, comment=request.content,
        is_description=updates_dict.get('is_description'),
        timestamp=timestamp, importer_id=importer_id)

    move_comment = None
    if move_to_project:
      old_text_ref = 'issue %s:%s' % (issue.project_name, issue.local_id)
      tracker_fulltext.UnindexIssues([issue.issue_id])
      moved_back_iids = self._services.issue.MoveIssues(
          mar.cnxn, move_to_project, [issue], self._services.user)
      new_text_ref = 'issue %s:%s' % (issue.project_name, issue.local_id)
      if issue.issue_id in moved_back_iids:
        content = 'Moved %s back to %s again.' % (old_text_ref, new_text_ref)
      else:
        content = 'Moved %s to now be %s.' % (old_text_ref, new_text_ref)
      move_comment = self._services.issue.CreateIssueComment(
        mar.cnxn, issue, mar.auth.user_id, content, amendments=[
            tracker_bizobj.MakeProjectAmendment(move_to_project.project_name)])

    if 'merged_into' in updates_dict:
      new_starrers = tracker_helpers.GetNewIssueStarrers(
          mar.cnxn, self._services, [issue.issue_id], merge_into_issue.issue_id)
      tracker_helpers.AddIssueStarrers(
          mar.cnxn, self._services, mar,
          merge_into_issue.issue_id, merge_into_project, new_starrers)
      # Load target issue again to get the updated star count.
      merge_into_issue = self._services.issue.GetIssue(
        mar.cnxn, merge_into_issue.issue_id, use_cache=False)
      merge_comment_pb = tracker_helpers.MergeCCsAndAddComment(
        self._services, mar, issue, merge_into_issue)
      hostport = framework_helpers.GetHostPort(
          project_name=merge_into_issue.project_name)
      send_notifications.PrepareAndSendIssueChangeNotification(
          merge_into_issue.issue_id, hostport,
          mar.auth.user_id, send_email=True, comment_id=merge_comment_pb.id)

    tracker_fulltext.IndexIssues(
        mar.cnxn, [issue], self._services.user, self._services.issue,
        self._services.config)

    comment = comment or move_comment
    if comment is None:
      return api_pb2_v1.IssuesCommentsInsertResponse()

    cmnts = self._services.issue.GetCommentsForIssue(mar.cnxn, issue.issue_id)
    seq = len(cmnts) - 1

    if request.sendEmail:
      hostport = framework_helpers.GetHostPort(project_name=issue.project_name)
      send_notifications.PrepareAndSendIssueChangeNotification(
          issue.issue_id, hostport, comment.user_id, send_email=True,
          old_owner_id=old_owner_id, comment_id=comment.id)

    issue_perms = permissions.UpdateIssuePermissions(
        mar.perms, mar.project, issue, mar.auth.effective_ids,
        granted_perms=mar.granted_perms)
    commenter = self._services.user.GetUser(mar.cnxn, comment.user_id)
    can_delete = permissions.CanDeleteComment(
        comment, commenter, mar.auth.user_id, issue_perms)
    return api_pb2_v1.IssuesCommentsInsertResponse(
        id=seq,
        kind='monorail#issueComment',
        author=api_pb2_v1_helpers.convert_person(
            comment.user_id, mar.cnxn, self._services),
        content=comment.content,
        published=datetime.datetime.fromtimestamp(comment.timestamp),
        updates=api_pb2_v1_helpers.convert_amendments(
            issue, comment.amendments, mar, self._services),
        canDelete=can_delete)

  @monorail_api_method(
      api_pb2_v1.ISSUES_COMMENTS_LIST_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.IssuesCommentsListResponse,
      path='projects/{projectId}/issues/{issueId}/comments',
      http_method='GET',
      name='issues.comments.list')
  def issues_comments_list(self, mar, request):
    """List all comments for an issue."""
    issue = self._services.issue.GetIssueByLocalID(
        mar.cnxn, mar.project_id, request.issueId)
    comments = self._services.issue.GetCommentsForIssue(
        mar.cnxn, issue.issue_id)
    comments = [comment for comment in comments if not comment.approval_id]
    visible_comments = []
    for comment in comments[
        request.startIndex:(request.startIndex + request.maxResults)]:
      visible_comments.append(
          api_pb2_v1_helpers.convert_comment(
              issue, comment, mar, self._services, mar.granted_perms))

    return api_pb2_v1.IssuesCommentsListResponse(
        kind='monorail#issueCommentList',
        totalResults=len(comments),
        items=visible_comments)

  @monorail_api_method(
      api_pb2_v1.ISSUES_COMMENTS_DELETE_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.IssuesCommentsDeleteResponse,
      path='projects/{projectId}/issues/{issueId}/comments/{commentId}',
      http_method='POST',
      name='issues.comments.undelete')
  def issues_comments_undelete(self, mar, request):
    """Restore a deleted comment."""
    return self.aux_delete_comment(mar, request, False)

  @monorail_api_method(
      api_pb2_v1.APPROVALS_COMMENTS_LIST_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.ApprovalsCommentsListResponse,
      path='projects/{projectId}/issues/{issueId}/'
            'approvals/{approvalName}/comments',
      http_method='GET',
      name='approvals.comments.list')
  def approvals_comments_list(self, mar, request):
    """List all comments for an issue approval."""
    issue = self._services.issue.GetIssueByLocalID(
        mar.cnxn, mar.project_id, request.issueId)
    if not permissions.CanViewIssue(
        mar.auth.effective_ids, mar.perms, mar.project, issue,
        mar.granted_perms):
      raise permissions.PermissionException(
          'User is not allowed to view this issue (%s, %d)' %
          (request.projectId, request.issueId))
    config = self._services.config.GetProjectConfig(mar.cnxn, issue.project_id)
    approval_fd = tracker_bizobj.FindFieldDef(request.approvalName, config)
    if not approval_fd:
      raise endpoints.BadRequestException(
          'Field definition for %s not found in project config' %
          request.approvalName)
    comments = self._services.issue.GetCommentsForIssue(
        mar.cnxn, issue.issue_id)
    comments = [comment for comment in comments
                if comment.approval_id == approval_fd.field_id]
    visible_comments = []
    for comment in comments[
        request.startIndex:(request.startIndex + request.maxResults)]:
      visible_comments.append(
          api_pb2_v1_helpers.convert_approval_comment(
              issue, comment, mar, self._services, mar.granted_perms))

    return api_pb2_v1.ApprovalsCommentsListResponse(
        kind='monorail#approvalCommentList',
        totalResults=len(comments),
        items=visible_comments)

  @monorail_api_method(
      api_pb2_v1.APPROVALS_COMMENTS_INSERT_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.ApprovalsCommentsInsertResponse,
      path=("projects/{projectId}/issues/{issueId}/"
            "approvals/{approvalName}/comments"),
      http_method='POST',
      name='approvals.comments.insert')
  def approvals_comments_insert(self, mar, request):
    # type (...) -> mrproto.api_pb2_v1.ApprovalsCommentsInsertResponse
    """Add an approval comment."""
    approval_fd = tracker_bizobj.FindFieldDef(
        request.approvalName, mar.config)
    if not approval_fd or (
        approval_fd.field_type != tracker_pb2.FieldTypes.APPROVAL_TYPE):
      raise endpoints.BadRequestException(
          'Field definition for %s not found in project config' %
          request.approvalName)
    try:
      issue = self._services.issue.GetIssueByLocalID(
          mar.cnxn, mar.project_id, request.issueId)
    except exceptions.NoSuchIssueException:
      raise endpoints.BadRequestException(
          'Issue %s:%s not found' % (request.projectId, request.issueId))
    approval = tracker_bizobj.FindApprovalValueByID(
        approval_fd.field_id, issue.approval_values)
    if not approval:
      raise endpoints.BadRequestException(
          'Approval %s not found in issue.' % request.approvalName)

    if not permissions.CanCommentIssue(
        mar.auth.effective_ids, mar.perms, mar.project, issue,
        mar.granted_perms):
      raise permissions.PermissionException(
          'User is not allowed to comment on this issue (%s, %d)' %
          (request.projectId, request.issueId))

    if request.content and len(
        request.content) > tracker_constants.MAX_COMMENT_CHARS:
      raise endpoints.BadRequestException(
          'Comment is too long on this issue (%s, %d' %
          (request.projectId, request.issueId))

    updates_dict = {}
    if request.approvalUpdates:
      if request.approvalUpdates.fieldValues:
        # Block updating field values that don't belong to the approval.
        approvals_fds_by_name = {
            fd.field_name.lower(): fd
            for fd in mar.config.field_defs
            if fd.approval_id == approval_fd.field_id
        }
        for fv in request.approvalUpdates.fieldValues:
          if approvals_fds_by_name.get(fv.fieldName.lower()) is None:
            raise endpoints.BadRequestException(
              'Field defition for %s not found in %s subfields.' %
              (fv.fieldName, request.approvalName))
        (updates_dict['field_vals_add'], updates_dict['field_vals_remove'],
         updates_dict['fields_clear'], updates_dict['fields_labels_add'],
         updates_dict['fields_labels_remove']) = (
             api_pb2_v1_helpers.convert_field_values(
                 request.approvalUpdates.fieldValues, mar, self._services))
      if request.approvalUpdates.approvers:
        if not permissions.CanUpdateApprovers(
            mar.auth.effective_ids, mar.perms, mar.project,
            approval.approver_ids):
          raise permissions.PermissionException(
              'User is not allowed to update approvers')
        approvers_add, approvers_remove = api_pb2_v1_helpers.split_remove_add(
            request.approvalUpdates.approvers)
        updates_dict['approver_ids_add'] = list(
            self._services.user.LookupUserIDs(mar.cnxn, approvers_add,
              autocreate=True).values())
        updates_dict['approver_ids_remove'] = list(
            self._services.user.LookupUserIDs(mar.cnxn, approvers_remove,
              autocreate=True).values())
      if request.approvalUpdates.status:
        status = tracker_pb2.ApprovalStatus(
            api_pb2_v1.ApprovalStatus(request.approvalUpdates.status).number)
        if not permissions.CanUpdateApprovalStatus(
            mar.auth.effective_ids, mar.perms, mar.project,
            approval.approver_ids, status):
          raise permissions.PermissionException(
              'User is not allowed to make this status change')
        updates_dict['status'] = status
    approval_delta = tracker_bizobj.MakeApprovalDelta(
        updates_dict.get('status'), mar.auth.user_id,
        updates_dict.get('approver_ids_add', []),
        updates_dict.get('approver_ids_remove', []),
        updates_dict.get('field_vals_add', []),
        updates_dict.get('field_vals_remove', []),
        updates_dict.get('fields_clear', []),
        updates_dict.get('fields_labels_add', []),
        updates_dict.get('fields_labels_remove', []))
    comment = self._services.issue.DeltaUpdateIssueApproval(
        mar.cnxn, mar.auth.user_id, mar.config, issue, approval, approval_delta,
        comment_content=request.content,
        is_description=request.is_description)

    cmnts = self._services.issue.GetCommentsForIssue(mar.cnxn, issue.issue_id)
    seq = len(cmnts) - 1

    if request.sendEmail:
      hostport = framework_helpers.GetHostPort(project_name=issue.project_name)
      send_notifications.PrepareAndSendApprovalChangeNotification(
          issue.issue_id, approval.approval_id,
          hostport, comment.id, send_email=True)

    issue_perms = permissions.UpdateIssuePermissions(
        mar.perms, mar.project, issue, mar.auth.effective_ids,
        granted_perms=mar.granted_perms)
    commenter = self._services.user.GetUser(mar.cnxn, comment.user_id)
    can_delete = permissions.CanDeleteComment(
        comment, commenter, mar.auth.user_id, issue_perms)
    return api_pb2_v1.ApprovalsCommentsInsertResponse(
        id=seq,
        kind='monorail#approvalComment',
        author=api_pb2_v1_helpers.convert_person(
            comment.user_id, mar.cnxn, self._services),
        content=comment.content,
        published=datetime.datetime.fromtimestamp(comment.timestamp),
        approvalUpdates=api_pb2_v1_helpers.convert_approval_amendments(
            comment.amendments, mar, self._services),
        canDelete=can_delete)

  @monorail_api_method(
      api_pb2_v1.USERS_GET_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.UsersGetResponse,
      path='users/{userId}',
      http_method='GET',
      name='users.get')
  def users_get(self, mar, request):
    """Get a user."""
    owner_project_only = request.ownerProjectsOnly
    with work_env.WorkEnv(mar, self._services) as we:
      (visible_ownership, visible_deleted, visible_membership,
       visible_contrib) = we.GetUserProjects(
           mar.viewed_user_auth.effective_ids)

    project_list = []
    for proj in (visible_ownership + visible_deleted):
      config = self._services.config.GetProjectConfig(
          mar.cnxn, proj.project_id)
      templates = self._services.template.GetProjectTemplates(
          mar.cnxn, config.project_id)
      proj_result = api_pb2_v1_helpers.convert_project(
          proj, config, api_pb2_v1.Role.owner, templates)
      project_list.append(proj_result)
    if not owner_project_only:
      for proj in visible_membership:
        config = self._services.config.GetProjectConfig(
            mar.cnxn, proj.project_id)
        templates = self._services.template.GetProjectTemplates(
            mar.cnxn, config.project_id)
        proj_result = api_pb2_v1_helpers.convert_project(
            proj, config, api_pb2_v1.Role.member, templates)
        project_list.append(proj_result)
      for proj in visible_contrib:
        config = self._services.config.GetProjectConfig(
            mar.cnxn, proj.project_id)
        templates = self._services.template.GetProjectTemplates(
            mar.cnxn, config.project_id)
        proj_result = api_pb2_v1_helpers.convert_project(
            proj, config, api_pb2_v1.Role.contributor, templates)
        project_list.append(proj_result)

    return api_pb2_v1.UsersGetResponse(
        id=str(mar.viewed_user_auth.user_id),
        kind='monorail#user',
        projects=project_list,
    )

  @monorail_api_method(
      api_pb2_v1.ISSUES_GET_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.IssuesGetInsertResponse,
      path='projects/{projectId}/issues/{issueId}',
      http_method='GET',
      name='issues.get')
  def issues_get(self, mar, request):
    """Get an issue."""
    issue = self._services.issue.GetIssueByLocalID(
        mar.cnxn, mar.project_id, request.issueId)

    with work_env.WorkEnv(mar, self._services) as we:
      migrated_id = we.GetIssueMigratedID(
          request.projectId, request.issueId, issue.labels)

    return api_pb2_v1_helpers.convert_issue(
        api_pb2_v1.IssuesGetInsertResponse, issue, mar, self._services,
        migrated_id)

  @monorail_api_method(
      api_pb2_v1.ISSUES_INSERT_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.IssuesGetInsertResponse,
      path='projects/{projectId}/issues',
      http_method='POST',
      name='issues.insert')
  def issues_insert(self, mar, request):
    """Add a new issue."""
    if not mar.perms.CanUsePerm(
        permissions.CREATE_ISSUE, mar.auth.effective_ids, mar.project, []):
      raise permissions.PermissionException(
          'The requester %s is not allowed to create issues for project %s.' %
          (mar.auth.email, mar.project_name))

    with work_env.WorkEnv(mar, self._services) as we:
      owner_id = framework_constants.NO_USER_SPECIFIED
      if request.owner and request.owner.name:
        try:
          owner_id = self._services.user.LookupUserID(
              mar.cnxn, request.owner.name)
        except exceptions.NoSuchUserException:
          raise endpoints.BadRequestException(
              'The specified owner %s does not exist.' % request.owner.name)

      cc_ids = []
      request.cc = [cc for cc in request.cc if cc]
      if request.cc:
        cc_ids = list(self._services.user.LookupUserIDs(
            mar.cnxn, [ap.name for ap in request.cc],
            autocreate=True).values())
      comp_ids = api_pb2_v1_helpers.convert_component_ids(
          mar.config, request.components)
      fields_add, _, _, fields_labels, _ = (
          api_pb2_v1_helpers.convert_field_values(
              request.fieldValues, mar, self._services))

      field_helpers.ValidateLabels(
          mar.cnxn,
          self._services,
          mar.project_id,
          fields_labels,
          ezt_errors=mar.errors)
      if mar.errors.AnyErrors():
        raise endpoints.BadRequestException(
            'Invalid field values: %s' % mar.errors.labels)

      field_helpers.ValidateCustomFields(
          mar.cnxn, self._services, fields_add, mar.config, mar.project,
          ezt_errors=mar.errors)
      if mar.errors.AnyErrors():
        raise endpoints.BadRequestException(
            'Invalid field values: %s' % mar.errors.custom_fields)

      logging.info('request.author is %r', request.author)
      reporter_id, timestamp = self.parse_imported_reporter(mar, request)
      # To preserve previous behavior, do not raise filter rule errors.
      try:
        new_issue, _ = we.CreateIssue(
            mar.project_id,
            request.summary,
            request.status,
            owner_id,
            cc_ids,
            request.labels + fields_labels,
            fields_add,
            comp_ids,
            request.description,
            blocked_on=api_pb2_v1_helpers.convert_issueref_pbs(
                request.blockedOn, mar, self._services),
            blocking=api_pb2_v1_helpers.convert_issueref_pbs(
                request.blocking, mar, self._services),
            reporter_id=reporter_id,
            timestamp=timestamp,
            send_email=request.sendEmail,
            raise_filter_errors=False)
        we.StarIssue(new_issue, True)
      except exceptions.InputException as e:
        raise endpoints.BadRequestException(str(e))

    return api_pb2_v1_helpers.convert_issue(
        api_pb2_v1.IssuesGetInsertResponse, new_issue, mar, self._services)

  @monorail_api_method(
      api_pb2_v1.ISSUES_LIST_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.IssuesListResponse,
      path='projects/{projectId}/issues',
      http_method='GET',
      name='issues.list')
  def issues_list(self, mar, request):
    """List issues for projects."""
    if request.additionalProject:
      for project_name in request.additionalProject:
        project = self._services.project.GetProjectByName(
            mar.cnxn, project_name)
        if project and not permissions.UserCanViewProject(
            mar.auth.user_pb, mar.auth.effective_ids, project):
          raise permissions.PermissionException(
              'The user %s has no permission for project %s' %
              (mar.auth.email, project_name))
    # TODO(jrobbins): This should go through work_env.
    pipeline = frontendsearchpipeline.FrontendSearchPipeline(
        mar.cnxn,
        self._services,
        mar.auth, [mar.me_user_id],
        mar.query,
        mar.query_project_names,
        mar.num,
        mar.start,
        mar.can,
        mar.group_by_spec,
        mar.sort_spec,
        mar.warnings,
        mar.errors,
        mar.use_cached_searches,
        mar.profiler,
        project=mar.project)
    if not mar.errors.AnyErrors():
      pipeline.SearchForIIDs()
      pipeline.MergeAndSortIssues()
      pipeline.Paginate()
    else:
      raise endpoints.BadRequestException(mar.errors.query)

    issue_list = [
        api_pb2_v1_helpers.convert_issue(
            api_pb2_v1.IssueWrapper, r, mar, self._services)
        for r in pipeline.visible_results]
    return api_pb2_v1.IssuesListResponse(
        kind='monorail#issueList',
        totalResults=pipeline.total_count,
        items=issue_list)

  @monorail_api_method(
      api_pb2_v1.GROUPS_SETTINGS_LIST_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.GroupsSettingsListResponse,
      path='groupsettings',
      http_method='GET',
      name='groups.settings.list')
  def groups_settings_list(self, mar, request):
    """List all group settings."""
    all_groups = self._services.usergroup.GetAllUserGroupsInfo(mar.cnxn)
    group_settings = []
    for g in all_groups:
      setting = g[2]
      wrapper = api_pb2_v1_helpers.convert_group_settings(g[0], setting)
      if not request.importedGroupsOnly or wrapper.ext_group_type:
        group_settings.append(wrapper)
    return api_pb2_v1.GroupsSettingsListResponse(
        groupSettings=group_settings)

  @monorail_api_method(
      api_pb2_v1.GROUPS_CREATE_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.GroupsCreateResponse,
      path='groups',
      http_method='POST',
      name='groups.create')
  def groups_create(self, mar, request):
    """Create a new user group."""
    if not permissions.CanCreateGroup(mar.perms):
      raise permissions.PermissionException(
          'The user is not allowed to create groups.')

    user_dict = self._services.user.LookupExistingUserIDs(
        mar.cnxn, [request.groupName])
    if request.groupName.lower() in user_dict:
      raise exceptions.GroupExistsException(
          'group %s already exists' % request.groupName)

    if request.ext_group_type:
      ext_group_type = str(request.ext_group_type).lower()
    else:
      ext_group_type = None
    group_id = self._services.usergroup.CreateGroup(
        mar.cnxn, self._services, request.groupName,
        str(request.who_can_view_members).lower(),
        ext_group_type)

    return api_pb2_v1.GroupsCreateResponse(
        groupID=group_id)

  @monorail_api_method(
      api_pb2_v1.GROUPS_GET_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.GroupsGetResponse,
      path='groups/{groupName}',
      http_method='GET',
      name='groups.get')
  def groups_get(self, mar, request):
    """Get a group's settings and users."""
    if not mar.viewed_user_auth:
      raise exceptions.NoSuchUserException(request.groupName)
    group_id = mar.viewed_user_auth.user_id
    group_settings = self._services.usergroup.GetGroupSettings(
        mar.cnxn, group_id)
    member_ids, owner_ids = self._services.usergroup.LookupAllMembers(
          mar.cnxn, [group_id])
    (owned_project_ids, membered_project_ids,
     contrib_project_ids) = self._services.project.GetUserRolesInAllProjects(
         mar.cnxn, mar.auth.effective_ids)
    project_ids = owned_project_ids.union(
        membered_project_ids).union(contrib_project_ids)
    if not permissions.CanViewGroupMembers(
        mar.perms, mar.auth.effective_ids, group_settings, member_ids[group_id],
        owner_ids[group_id], project_ids):
      raise permissions.PermissionException(
          'The user is not allowed to view this group.')

    member_ids, owner_ids = self._services.usergroup.LookupMembers(
        mar.cnxn, [group_id])

    member_emails = list(self._services.user.LookupUserEmails(
        mar.cnxn, member_ids[group_id]).values())
    owner_emails = list(self._services.user.LookupUserEmails(
        mar.cnxn, owner_ids[group_id]).values())

    return api_pb2_v1.GroupsGetResponse(
      groupID=group_id,
      groupSettings=api_pb2_v1_helpers.convert_group_settings(
          request.groupName, group_settings),
      groupOwners=owner_emails,
      groupMembers=member_emails)

  @monorail_api_method(
      api_pb2_v1.GROUPS_UPDATE_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.GroupsUpdateResponse,
      path='groups/{groupName}',
      http_method='POST',
      name='groups.update')
  def groups_update(self, mar, request):
    """Update a group's settings and users."""
    group_id = mar.viewed_user_auth.user_id
    member_ids_dict, owner_ids_dict = self._services.usergroup.LookupMembers(
        mar.cnxn, [group_id])
    owner_ids = owner_ids_dict.get(group_id, [])
    member_ids = member_ids_dict.get(group_id, [])
    if not permissions.CanEditGroup(
        mar.perms, mar.auth.effective_ids, owner_ids):
      raise permissions.PermissionException(
          'The user is not allowed to edit this group.')

    group_settings = self._services.usergroup.GetGroupSettings(
        mar.cnxn, group_id)
    if (request.who_can_view_members or request.ext_group_type
        or request.last_sync_time or request.friend_projects):
      group_settings.who_can_view_members = (
          request.who_can_view_members or group_settings.who_can_view_members)
      group_settings.ext_group_type = (
          request.ext_group_type or group_settings.ext_group_type)
      group_settings.last_sync_time = (
          request.last_sync_time or group_settings.last_sync_time)
      if framework_constants.NO_VALUES in request.friend_projects:
        group_settings.friend_projects = []
      else:
        id_dict = self._services.project.LookupProjectIDs(
            mar.cnxn, request.friend_projects)
        group_settings.friend_projects = (
            list(id_dict.values()) or group_settings.friend_projects)
      self._services.usergroup.UpdateSettings(
          mar.cnxn, group_id, group_settings)

    if request.groupOwners or request.groupMembers:
      self._services.usergroup.RemoveMembers(
          mar.cnxn, group_id, owner_ids + member_ids)
      owners_dict = self._services.user.LookupUserIDs(
          mar.cnxn, request.groupOwners, autocreate=True)
      self._services.usergroup.UpdateMembers(
          mar.cnxn, group_id, list(owners_dict.values()), 'owner')
      members_dict = self._services.user.LookupUserIDs(
          mar.cnxn, request.groupMembers, autocreate=True)
      self._services.usergroup.UpdateMembers(
          mar.cnxn, group_id, list(members_dict.values()), 'member')

    return api_pb2_v1.GroupsUpdateResponse()

  @monorail_api_method(
      api_pb2_v1.COMPONENTS_LIST_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.ComponentsListResponse,
      path='projects/{projectId}/components',
      http_method='GET',
      name='components.list')
  def components_list(self, mar, _request):
    """List all components of a given project."""
    config = self._services.config.GetProjectConfig(mar.cnxn, mar.project_id)
    components = [api_pb2_v1_helpers.convert_component_def(
        cd, mar, self._services) for cd in config.component_defs]
    return api_pb2_v1.ComponentsListResponse(
        components=components)

  @monorail_api_method(
      api_pb2_v1.COMPONENTS_CREATE_REQUEST_RESOURCE_CONTAINER,
      api_pb2_v1.Component,
      path='projects/{projectId}/components',
      http_method='POST',
      name='components.create')
  def components_create(self, mar, request):
    """Create a component."""
    if not permissions.CanEditProjectConfig(mar, self._services):
      raise permissions.PermissionException(
          'User is not allowed to create components for this project')

    config = self._services.config.GetProjectConfig(mar.cnxn, mar.project_id)
    leaf_name = request.componentName
    if not tracker_constants.COMPONENT_NAME_RE.match(leaf_name):
      raise exceptions.InvalidComponentNameException(
          'The component name %s is invalid.' % leaf_name)

    parent_path = request.parentPath
    if parent_path:
      parent_def = tracker_bizobj.FindComponentDef(parent_path, config)
      if not parent_def:
        raise exceptions.NoSuchComponentException(
            'Parent component %s does not exist.' % parent_path)
      if not permissions.CanEditComponentDef(mar, self._services, parent_def,
                                             config):
        raise permissions.PermissionException(
            'User is not allowed to add a subcomponent to component %s' %
            parent_path)

      path = '%s>%s' % (parent_path, leaf_name)
    else:
      path = leaf_name

    if tracker_bizobj.FindComponentDef(path, config):
      raise exceptions.InvalidComponentNameException(
          'The name %s is already in use.' % path)

    created = int(time.time())
    user_emails = set()
    user_emails.update([mar.auth.email] + request.admin + request.cc)
    user_ids_dict = self._services.user.LookupUserIDs(
        mar.cnxn, list(user_emails), autocreate=False)
    request.admin = [admin for admin in request.admin if admin]
    admin_ids = [user_ids_dict[uname] for uname in request.admin]
    request.cc = [cc for cc in request.cc if cc]
    cc_ids = [user_ids_dict[uname] for uname in request.cc]
    label_ids = []  # TODO(jrobbins): allow API clients to specify this too.

    component_id = self._services.config.CreateComponentDef(
        mar.cnxn, mar.project_id, path, request.description, request.deprecated,
        admin_ids, cc_ids, created, user_ids_dict[mar.auth.email], label_ids)

    return api_pb2_v1.Component(
        componentId=component_id,
        projectName=request.projectId,
        componentPath=path,
        description=request.description,
        admin=request.admin,
        cc=request.cc,
        deprecated=request.deprecated,
        created=datetime.datetime.fromtimestamp(created),
        creator=mar.auth.email)

  @monorail_api_method(
      api_pb2_v1.COMPONENTS_DELETE_REQUEST_RESOURCE_CONTAINER,
      message_types.VoidMessage,
      path='projects/{projectId}/components/{componentPath}',
      http_method='DELETE',
      name='components.delete')
  def components_delete(self, mar, request):
    """Delete a component."""
    config = self._services.config.GetProjectConfig(mar.cnxn, mar.project_id)
    component_path = request.componentPath
    component_def = tracker_bizobj.FindComponentDef(
        component_path, config)
    if not component_def:
      raise exceptions.NoSuchComponentException(
          'The component %s does not exist.' % component_path)
    if not permissions.CanViewComponentDef(
        mar.auth.effective_ids, mar.perms, mar.project, component_def):
      raise permissions.PermissionException(
          'User is not allowed to view this component %s' % component_path)
    if not permissions.CanEditComponentDef(mar, self._services, component_def,
                                           config):
      raise permissions.PermissionException(
          'User is not allowed to delete this component %s' % component_path)

    allow_delete = not tracker_bizobj.FindDescendantComponents(
        config, component_def)
    if not allow_delete:
      raise permissions.PermissionException(
          'User tried to delete component that had subcomponents')

    self._services.issue.DeleteComponentReferences(
        mar.cnxn, component_def.component_id)
    self._services.config.DeleteComponentDef(
        mar.cnxn, mar.project_id, component_def.component_id)
    return message_types.VoidMessage()

  @monorail_api_method(
      api_pb2_v1.COMPONENTS_UPDATE_REQUEST_RESOURCE_CONTAINER,
      message_types.VoidMessage,
      path='projects/{projectId}/components/{componentPath}',
      http_method='POST',
      name='components.update')
  def components_update(self, mar, request):
    """Update a component."""
    config = self._services.config.GetProjectConfig(mar.cnxn, mar.project_id)
    component_path = request.componentPath
    component_def = tracker_bizobj.FindComponentDef(
        component_path, config)
    if not component_def:
      raise exceptions.NoSuchComponentException(
          'The component %s does not exist.' % component_path)
    if not permissions.CanViewComponentDef(
        mar.auth.effective_ids, mar.perms, mar.project, component_def):
      raise permissions.PermissionException(
          'User is not allowed to view this component %s' % component_path)
    if not permissions.CanEditComponentDef(mar, self._services, component_def,
                                           config):
      raise permissions.PermissionException(
          'User is not allowed to edit this component %s' % component_path)

    original_path = component_def.path
    new_path = component_def.path
    new_docstring = component_def.docstring
    new_deprecated = component_def.deprecated
    new_admin_ids = component_def.admin_ids
    new_cc_ids = component_def.cc_ids
    update_filterrule = False
    for update in request.updates:
      if update.field == api_pb2_v1.ComponentUpdateFieldID.LEAF_NAME:
        leaf_name = update.leafName
        if not tracker_constants.COMPONENT_NAME_RE.match(leaf_name):
          raise exceptions.InvalidComponentNameException(
              'The component name %s is invalid.' % leaf_name)

        if '>' in original_path:
          parent_path = original_path[:original_path.rindex('>')]
          new_path = '%s>%s' % (parent_path, leaf_name)
        else:
          new_path = leaf_name

        conflict = tracker_bizobj.FindComponentDef(new_path, config)
        if conflict and conflict.component_id != component_def.component_id:
          raise exceptions.InvalidComponentNameException(
              'The name %s is already in use.' % new_path)
        update_filterrule = True
      elif update.field == api_pb2_v1.ComponentUpdateFieldID.DESCRIPTION:
        new_docstring = update.description
      elif update.field == api_pb2_v1.ComponentUpdateFieldID.ADMIN:
        user_ids_dict = self._services.user.LookupUserIDs(
            mar.cnxn, list(update.admin), autocreate=True)
        new_admin_ids = list(set(user_ids_dict.values()))
      elif update.field == api_pb2_v1.ComponentUpdateFieldID.CC:
        user_ids_dict = self._services.user.LookupUserIDs(
            mar.cnxn, list(update.cc), autocreate=True)
        new_cc_ids = list(set(user_ids_dict.values()))
        update_filterrule = True
      elif update.field == api_pb2_v1.ComponentUpdateFieldID.DEPRECATED:
        new_deprecated = update.deprecated
      else:
        logging.error('Unknown component field %r', update.field)

    new_modified = int(time.time())
    new_modifier_id = self._services.user.LookupUserID(
        mar.cnxn, mar.auth.email, autocreate=False)
    logging.info(
        'Updating component id %d: path-%s, docstring-%s, deprecated-%s,'
        ' admin_ids-%s, cc_ids-%s modified by %s', component_def.component_id,
        new_path, new_docstring, new_deprecated, new_admin_ids, new_cc_ids,
        new_modifier_id)
    self._services.config.UpdateComponentDef(
        mar.cnxn, mar.project_id, component_def.component_id,
        path=new_path, docstring=new_docstring, deprecated=new_deprecated,
        admin_ids=new_admin_ids, cc_ids=new_cc_ids, modified=new_modified,
        modifier_id=new_modifier_id)

    # TODO(sheyang): reuse the code in componentdetails
    if original_path != new_path:
      # If the name changed then update all of its subcomponents as well.
      subcomponent_ids = tracker_bizobj.FindMatchingComponentIDs(
          original_path, config, exact=False)
      for subcomponent_id in subcomponent_ids:
        if subcomponent_id == component_def.component_id:
          continue
        subcomponent_def = tracker_bizobj.FindComponentDefByID(
            subcomponent_id, config)
        subcomponent_new_path = subcomponent_def.path.replace(
            original_path, new_path, 1)
        self._services.config.UpdateComponentDef(
            mar.cnxn, mar.project_id, subcomponent_def.component_id,
            path=subcomponent_new_path)

    if update_filterrule:
      filterrules_helpers.RecomputeAllDerivedFields(
          mar.cnxn, self._services, mar.project, config)

    return message_types.VoidMessage()


@endpoints.api(name='monorail_client_configs', version='v1',
               description='Monorail API client configs.')
class ClientConfigApi(remote.Service):

  # Class variables. Handy to mock.
  _services = None
  _mar = None

  @classmethod
  def _set_services(cls, services):
    cls._services = services

  def mar_factory(self, request, cnxn):
    if not self._mar:
      self._mar = monorailrequest.MonorailApiRequest(
          request, self._services, cnxn=cnxn)
    return self._mar

  @endpoints.method(
      message_types.VoidMessage,
      message_types.VoidMessage,
      path='client_configs',
      http_method='POST',
      name='client_configs.update')
  def client_configs_update(self, request):
    if self._services is None:
      self._set_services(service_manager.set_up_services())
    mar = self.mar_factory(request, sql.MonorailConnection())
    if not mar.perms.HasPerm(permissions.ADMINISTER_SITE, None, None):
      raise permissions.PermissionException(
          'The requester %s is not allowed to update client configs.' %
           mar.auth.email)

    ROLE_DICT = {
        1: permissions.COMMITTER_ROLE,
        2: permissions.CONTRIBUTOR_ROLE,
    }

    client_config = client_config_svc.GetClientConfigSvc()

    cfg = client_config.GetConfigs()
    if not cfg:
      msg = 'Failed to fetch client configs.'
      logging.error(msg)
      raise endpoints.InternalServerErrorException(msg)

    for client in cfg.clients:
      if not client.client_email:
        continue
      # 1: create the user if non-existent
      user_id = self._services.user.LookupUserID(
          mar.cnxn, client.client_email, autocreate=True)
      user_pb = self._services.user.GetUser(mar.cnxn, user_id)

      logging.info('User ID %d for email %s', user_id, client.client_email)

      # 2: set period and lifetime limit
      # new_soft_limit, new_hard_limit, new_lifetime_limit
      new_limit_tuple = (
          client.period_limit, client.period_limit, client.lifetime_limit)
      action_limit_updates = {'api_request': new_limit_tuple}
      self._services.user.UpdateUserSettings(
          mar.cnxn, user_id, user_pb, action_limit_updates=action_limit_updates)

      logging.info('Updated api request limit %r', new_limit_tuple)

      # 3: Update project role and extra perms
      projects_dict = self._services.project.GetAllProjects(mar.cnxn)
      project_name_to_ids = {
          p.project_name: p.project_id for p in projects_dict.values()}

      # Set project role and extra perms
      for perm in client.project_permissions:
        project_ids = self._GetProjectIDs(perm.project, project_name_to_ids)
        logging.info('Matching projects %r for name %s',
                     project_ids, perm.project)

        role = ROLE_DICT[perm.role]
        for p_id in project_ids:
          project = projects_dict[p_id]
          people_list = []
          if role == 'owner':
            people_list = project.owner_ids
          elif role == 'committer':
            people_list = project.committer_ids
          elif role == 'contributor':
            people_list = project.contributor_ids
          # Onlu update role/extra perms iff changed
          if not user_id in people_list:
            logging.info('Update project %s role %s for user %s',
                         project.project_name, role, client.client_email)
            owner_ids, committer_ids, contributor_ids = (
                project_helpers.MembersWithGivenIDs(project, {user_id}, role))
            self._services.project.UpdateProjectRoles(
                mar.cnxn, p_id, owner_ids, committer_ids,
                contributor_ids)
          if perm.extra_permissions:
            logging.info('Update project %s extra perm %s for user %s',
                         project.project_name, perm.extra_permissions,
                         client.client_email)
            self._services.project.UpdateExtraPerms(
                mar.cnxn, p_id, user_id, list(perm.extra_permissions))

    mar.CleanUp()
    return message_types.VoidMessage()

  def _GetProjectIDs(self, project_str, project_name_to_ids):
    result = []
    if any(ch in project_str for ch in ['*', '+', '?', '.']):
      pattern = re.compile(project_str)
      for p_name in project_name_to_ids.keys():
        if pattern.match(p_name):
          project_id = project_name_to_ids.get(p_name)
          if project_id:
            result.append(project_id)
    else:
      project_id = project_name_to_ids.get(project_str)
      if project_id:
        result.append(project_id)

    if not result:
      logging.warning('Cannot find projects for specified name %s',
                      project_str)
    return result
