# Copyright 2014 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.

"""User-related functions, including access control list implementation.

See Acl message in proto/project_config.proto.
"""

import collections
import logging
import os
import threading

from google.appengine.api import app_identity
from google.appengine.ext import ndb

from components import auth
from components import utils

from protorpc import messages
from go.chromium.org.luci.buildbucket.proto import project_config_pb2
import config
import errors

# Group whitelisting users to update builds. They are expected to be robots.
UPDATE_BUILD_ALLOWED_USERS = 'buildbucket-update-build-users'


################################################################################
## Permissions-based API (implemented in terms of Buildbucket roles for now).

ALL_PERMISSIONS = set()


def _permission(name):
  perm = auth.Permission(name)
  ALL_PERMISSIONS.add(perm)
  return perm


# Builds permissions.

# See all information about a build.
PERM_BUILDS_GET = _permission('buildbucket.builds.get')
# List and search builds in a bucket.
PERM_BUILDS_LIST = _permission('buildbucket.builds.list')
# Schedule new builds in the bucket.
PERM_BUILDS_ADD = _permission('buildbucket.builds.add')
# Cancel a build in the bucket.
PERM_BUILDS_CANCEL = _permission('buildbucket.builds.cancel')
# Lease and control a build via v1 API, deprecated.
PERM_BUILDS_LEASE = _permission('buildbucket.builds.lease')
# Unlease and reset state of an existing build via v1 API, deprecated.
PERM_BUILDS_RESET = _permission('buildbucket.builds.reset')

# Builders permissions.

# See existence and metadata of a builder (but not its builds).
PERM_BUILDERS_GET = _permission('buildbucket.builders.get')
# List and search builders (but not builds).
PERM_BUILDERS_LIST = _permission('buildbucket.builders.list')
# Set the next build number.
PERM_BUILDERS_SET_NUM = _permission('buildbucket.builders.setBuildNumber')

# Bucket permissions.

# See existence of a bucket, used only by v1 APIs, deprecated.
PERM_BUCKETS_GET = _permission('buildbucket.buckets.get')
# Delete all scheduled builds from a bucket.
PERM_BUCKETS_DELETE_BUILDS = _permission('buildbucket.buckets.deleteBuilds')
# Pause/resume leasing builds in a bucket via v1 API, deprecated.
PERM_BUCKETS_PAUSE = _permission('buildbucket.buckets.pause')

# Forbid adding more permission from other modules or tests after this point.
ALL_PERMISSIONS = frozenset(ALL_PERMISSIONS)

# Maps a Permission to a minimum required project_config_pb2.Acl.Role.
PERM_TO_MIN_ROLE = {
    # Reader.
    PERM_BUILDS_GET: project_config_pb2.Acl.READER,
    PERM_BUILDS_LIST: project_config_pb2.Acl.READER,
    PERM_BUILDERS_GET: project_config_pb2.Acl.READER,
    PERM_BUILDERS_LIST: project_config_pb2.Acl.READER,
    PERM_BUCKETS_GET: project_config_pb2.Acl.READER,

    # Scheduler.
    PERM_BUILDS_ADD: project_config_pb2.Acl.SCHEDULER,
    PERM_BUILDS_CANCEL: project_config_pb2.Acl.SCHEDULER,

    # Writer.
    PERM_BUILDS_LEASE: project_config_pb2.Acl.WRITER,
    PERM_BUILDS_RESET: project_config_pb2.Acl.WRITER,
    PERM_BUILDERS_SET_NUM: project_config_pb2.Acl.WRITER,
    PERM_BUCKETS_DELETE_BUILDS: project_config_pb2.Acl.WRITER,
    PERM_BUCKETS_PAUSE: project_config_pb2.Acl.WRITER,
}
assert sorted(PERM_TO_MIN_ROLE.keys()) == sorted(ALL_PERMISSIONS)


@ndb.tasklet
def has_perm_async(perm, bucket_id):
  """Returns True if the caller has the given permission in the bucket.

  Args:
    perm: an instance of auth.Permission.
    bucket_id: a bucket ID string, i.e. "<project>/<bucket>".
  """
  assert isinstance(perm, auth.Permission), perm
  assert perm in ALL_PERMISSIONS, perm
  config.validate_bucket_id(bucket_id)

  # Convert to a realm ID (it uses ':' separator).
  project, bucket = config.parse_bucket_id(bucket_id)
  realm = '%s:%s' % (project, bucket)

  # In buckets that have realm ACLs configured, enforce them.
  if auth.should_enforce_realm_acl(realm):
    logging.info('crbug.com/1091604: enforcing realm ACLs for %r', realm)
    if auth.has_permission(perm, [realm]):
      raise ndb.Return(True)

    # For compatibility with legacy ALCs, administrators have implicit access to
    # everything. Log when this rule is invoked, since it's surprising and it
    # something we might want to get rid of after everything is migrated to
    # Realms.
    if auth.is_admin():
      logging.warning(
          'ADMIN_ACCESS: %r does not have permission %r in bucket %r, '
          'but they are in %r group and are allowed to proceed',
          auth.get_current_identity().to_bytes(), perm, bucket_id,
          auth.ADMIN_GROUP
      )
      raise ndb.Return(True)

    raise ndb.Return(False)

  # Get the result of the legacy ACL check.
  role = yield get_role_async_deprecated(bucket_id)
  outcome = role is not None and role >= PERM_TO_MIN_ROLE[perm]

  # Compare it to realm ACLs, logs the difference.
  auth.has_permission_dryrun(
      perm,
      [realm],
      expected_result=outcome,
      admin_group=auth.ADMIN_GROUP,
      tracking_bug='crbug.com/1091604',
  )

  # But still use legacy ACLs.
  raise ndb.Return(outcome)


def has_perm(perm, bucket_id):
  """Returns True if the caller has the given permission in the bucket.

  Args:
    perm: an instance of auth.Permission.
    bucket_id: a bucket ID string, i.e. "<project>/<bucket>".
  """
  return has_perm_async(perm, bucket_id).get_result()


def filter_buckets_by_perm(perm, bucket_ids):
  """Filters given buckets keeping only ones the caller has the permission in.

  Note that this function is not async!

  Args:
    perm: an instance of auth.Permission.
    bucket_ids: an iterable with bucket IDs.

  Returns:
    A set of bucket IDs.
  """
  pairs = utils.async_apply(
      bucket_ids if isinstance(bucket_ids, set) else set(bucket_ids),
      lambda bid: has_perm_async(perm, bid),
      unordered=True,
  )
  return {bid for bid, has_perm in pairs if has_perm}


def buckets_by_perm_async(perm):
  """Returns buckets that the caller has the given permission in.

  Results are memcached for 10 minutes per (identity, perm) pair.

  Args:
    perm: an instance of auth.Permission.

  Returns:
    A set of bucket IDs.
  """
  assert isinstance(perm, auth.Permission), perm
  assert perm in ALL_PERMISSIONS, perm

  identity = auth.get_current_identity()
  identity_str = identity.to_bytes()

  @ndb.tasklet
  def impl():
    ctx = ndb.get_context()
    cache_key = 'buckets_by_perm/%s/%s' % (identity_str, perm)
    matching_buckets = yield ctx.memcache_get(cache_key)
    if matching_buckets is not None:
      raise ndb.Return(matching_buckets)

    logging.info('Computing a set of buckets %r has %r in', identity_str, perm)
    all_buckets = yield config.get_all_bucket_ids_async()
    per_bucket = yield [has_perm_async(perm, bid) for bid in all_buckets]
    matching_buckets = {bid for bid, has in zip(all_buckets, per_bucket) if has}

    # Cache for 10 min
    yield ctx.memcache_set(cache_key, matching_buckets, 10 * 60)
    raise ndb.Return(matching_buckets)

  return _get_or_create_cached_future(
      identity, 'buckets_by_perm/%s' % perm, impl
  )


################################################################################
## Role definitions (DEPRECATED).


class Action(messages.Enum):
  # Schedule a build.
  ADD_BUILD = 1
  # Get information about a build.
  VIEW_BUILD = 2
  # Lease a build for execution. Normally done by build systems.
  LEASE_BUILD = 3
  # Cancel an existing build. Does not require a lease key.
  CANCEL_BUILD = 4
  # Unlease and reset state of an existing build. Normally done by admins.
  RESET_BUILD = 5
  # Search for builds or get a list of scheduled builds.
  SEARCH_BUILDS = 6
  # Delete all scheduled builds from a bucket.
  DELETE_SCHEDULED_BUILDS = 9
  # Know about bucket existence and read its info.
  ACCESS_BUCKET = 10
  # Pause builds for a given bucket.
  PAUSE_BUCKET = 11
  # Set the number for the next build in a builder.
  SET_NEXT_NUMBER = 12


# Maps an Action to a description.
ACTION_DESCRIPTIONS = {
    Action.ADD_BUILD:
        'Schedule a build.',
    Action.VIEW_BUILD:
        'Get information about a build.',
    Action.LEASE_BUILD:
        'Lease a build for execution.',
    Action.CANCEL_BUILD:
        'Cancel an existing build. Does not require a lease key.',
    Action.RESET_BUILD:
        'Unlease and reset state of an existing build.',
    Action.SEARCH_BUILDS:
        'Search for builds or get a list of scheduled builds.',
    Action.DELETE_SCHEDULED_BUILDS:
        'Delete all scheduled builds from a bucket.',
    Action.ACCESS_BUCKET:
        'Know about a bucket\'s existence and read its info.',
    Action.PAUSE_BUCKET:
        'Pause builds for a given bucket.',
    Action.SET_NEXT_NUMBER:
        'Set the number for the next build in a builder.',
}

# Maps an Action to a permission, assuming Access API is used only by Milo.
ACTION_TO_PERM = {
    Action.ADD_BUILD:
        PERM_BUILDS_ADD,
    Action.VIEW_BUILD:
        PERM_BUILDS_GET,
    Action.LEASE_BUILD:
        PERM_BUILDS_LEASE,
    Action.CANCEL_BUILD:
        PERM_BUILDS_CANCEL,
    Action.RESET_BUILD:
        PERM_BUILDS_RESET,
    Action.SEARCH_BUILDS:
        PERM_BUILDS_LIST,
    Action.DELETE_SCHEDULED_BUILDS:
        PERM_BUCKETS_DELETE_BUILDS,
    # Milo checks ACCESS_BUCKET exclusively to test visibility of builders.
    Action.ACCESS_BUCKET:
        PERM_BUILDERS_GET,
    Action.PAUSE_BUCKET:
        PERM_BUCKETS_PAUSE,
    Action.SET_NEXT_NUMBER:
        PERM_BUILDERS_SET_NUM,
}

# Reverse, since it is more useful in the actual implementation.
PERM_TO_ACTION = {perm: action for action, perm in ACTION_TO_PERM.items()}


################################################################################
## Granular actions. API uses these.


@ndb.tasklet
def can_update_build_async():  # pragma: no cover
  """Returns if the current identity is whitelisted to update builds."""
  # TODO(crbug.com/1091604): Implementing using has_perm_async.
  raise ndb.Return(auth.is_group_member(UPDATE_BUILD_ALLOWED_USERS))


################################################################################
## Implementation.


def get_role_async_deprecated(bucket_id):
  """Returns the most permissive role of the current user in |bucket_id|.

  The most permissive role is the role that allows most actions, e.g. WRITER
  is more permissive than READER.

  Returns None if there's no such bucket or the current identity has no roles in
  it at all.
  """
  config.validate_bucket_id(bucket_id)

  identity = auth.get_current_identity()
  identity_str = identity.to_bytes()

  @ndb.tasklet
  def impl():
    ctx = ndb.get_context()
    cache_key = 'role/%s/%s' % (identity_str, bucket_id)
    cache = yield ctx.memcache_get(cache_key)
    if cache is not None:
      raise ndb.Return(cache[0])

    _, bucket_cfg = yield config.get_bucket_async(bucket_id)
    if not bucket_cfg:
      raise ndb.Return(None)
    if auth.is_admin(identity):
      raise ndb.Return(project_config_pb2.Acl.WRITER)

    # A LUCI service calling us in the context of some project is allowed to
    # do anything it wants in that project. We trust all LUCI services to do
    # authorization on their own for this case. A cross-project request must be
    # explicitly authorized in Buildbucket ACLs though (so we proceed to the
    # bucket_cfg check below).
    if identity.is_project:
      project_id, _ = config.parse_bucket_id(bucket_id)
      if project_id == identity.name:
        raise ndb.Return(project_config_pb2.Acl.WRITER)

    # Roles are just numbers. The higher the number, the more permissions
    # the identity has. We exploit this here to get the single maximally
    # permissive role for the current identity.
    role = None
    for rule in bucket_cfg.acls:
      if rule.role <= role:
        continue
      if (rule.identity == identity_str or
          (rule.group and auth.is_group_member(rule.group, identity))):
        role = rule.role
    yield ctx.memcache_set(cache_key, (role,), time=60)
    raise ndb.Return(role)

  return _get_or_create_cached_future(identity, 'role/%s' % bucket_id, impl)


@ndb.tasklet
def permitted_actions_async(bucket_id):
  """Returns a tuple of actions (as Action enums) permitted to the caller."""
  per_perm = yield [has_perm_async(perm, bucket_id) for perm in PERM_TO_ACTION]
  actions = [
      PERM_TO_ACTION[perm] for perm, has in zip(PERM_TO_ACTION, per_perm) if has
  ]
  raise ndb.Return(tuple(sorted(actions)))


@utils.cache
def self_identity():  # pragma: no cover
  """Returns identity of the buildbucket app."""
  return auth.Identity('user', app_identity.get_service_account_name())


def delegate_async(target_service_host, identity=None, tag=''):
  """Mints a delegation token for the current identity."""
  tag = tag or ''
  identity = identity or auth.get_current_identity()

  # TODO(vadimsh): 'identity' here can be 'project:<...>' and we happily create
  # a delegation token for it, which is weird. Buildbucket should call Swarming
  # using 'project:<...>' identity directly, not through a delegation token.

  def impl():
    return auth.delegate_async(
        audience=[self_identity()],
        services=['https://%s' % target_service_host],
        impersonate=identity,
        tags=[tag] if tag else [],
    )

  return _get_or_create_cached_future(
      identity, 'delegation_token:%s:%s' % (target_service_host, tag), impl
  )


def current_identity_cannot(action_format, *args):  # pragma: no cover
  """Returns AuthorizationError."""
  action = action_format % args
  msg = 'User %s cannot %s' % (auth.get_current_identity().to_bytes(), action)
  logging.warning(msg)
  return auth.AuthorizationError(msg)


def parse_identity(identity):
  """Parses an identity string if it is a string."""
  if isinstance(identity, basestring):
    if not identity:  # pragma: no cover
      return None
    if ':' not in identity:  # pragma: no branch
      identity = 'user:%s' % identity
    try:
      identity = auth.Identity.from_bytes(identity)
    except ValueError as ex:
      raise errors.InvalidInputError('Invalid identity: %s' % ex)
  return identity


_thread_local = threading.local()


def _get_or_create_cached_future(identity, key, create_future):
  """Returns a future cached in the current GAE request context.

  Uses the pair (identity, key) as the caching key.

  Using this function may cause RuntimeError with a deadlock if the returned
  future is not waited for before leaving an ndb context, but that's a bug
  in the first place.
  """
  assert isinstance(identity, auth.Identity), identity
  full_key = (identity, key)

  # Docs:
  # https://cloud.google.com/appengine/docs/standard/python/how-requests-are-handled#request-ids
  req_id = os.environ['REQUEST_LOG_ID']
  cache = getattr(_thread_local, 'request_cache', {})
  if cache.get('request_id') != req_id:
    cache = {
        'request_id': req_id,
        'futures': {},
    }
    _thread_local.request_cache = cache

  fut_entry = cache['futures'].get(full_key)
  if fut_entry is None:
    fut_entry = {
        'future': create_future(),
        'ndb_context': ndb.get_context(),
    }
    cache['futures'][full_key] = fut_entry
  assert (
      fut_entry['future'].done() or
      ndb.get_context() is fut_entry['ndb_context']
  )
  return fut_entry['future']


def clear_request_cache():
  _thread_local.request_cache = {}
