Project import generated by Copybara.

GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/framework/authdata.py b/framework/authdata.py
new file mode 100644
index 0000000..3c1bee9
--- /dev/null
+++ b/framework/authdata.py
@@ -0,0 +1,145 @@
+# 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
+
+"""Classes to hold information parsed from a request.
+"""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+from google.appengine.api import users
+
+from proto import user_pb2
+from framework import framework_bizobj
+from framework import framework_views
+
+
+class AuthData(object):
+  """This object holds authentication data about a user.
+
+  This is used by MonorailRequest as it determines which user the
+  requester is authenticated as and fetches the user's data.  It can
+  also be used to lookup perms for user IDs specified in issue fields.
+
+  Attributes:
+    user_id: The user ID of the user (or 0 if not signed in).
+    effective_ids: A set of user IDs that includes the signed in user's
+        direct user ID and the user IDs of all their user groups.
+        This set will be empty for anonymous users.
+    user_view: UserView object for the signed-in user.
+    user_pb: User object for the signed-in user.
+    email: email address for the user, or None.
+  """
+
+  def __init__(self, user_id=0, email=None):
+    self.user_id = user_id
+    self.effective_ids = {user_id} if user_id else set()
+    self.user_view = None
+    self.user_pb = user_pb2.MakeUser(user_id)
+    self.email = email
+
+  @classmethod
+  def FromRequest(cls, cnxn, services):
+    """Determine auth information from the request and fetches user data.
+
+    If everything works and the user is signed in, then all of the public
+    attributes of the AuthData instance will be filled in appropriately.
+
+    Args:
+      cnxn: connection to the SQL database.
+      services: Interface to all persistence storage backends.
+
+    Returns:
+      A new AuthData object.
+    """
+    user = users.get_current_user()
+    if user is None:
+      return cls()
+    else:
+      # We create a User row for each user who visits the site.
+      # TODO(jrobbins): we should really only do it when they take action.
+      return cls.FromEmail(cnxn, user.email(), services, autocreate=True)
+
+  @classmethod
+  def FromEmail(cls, cnxn, email, services, autocreate=False):
+    """Determine auth information for the given user email address.
+
+    Args:
+      cnxn: monorail connection to the database.
+      email: string email address of the user.
+      services: connections to backend servers.
+      autocreate: set to True to create a new row in the Users table if needed.
+
+    Returns:
+      A new AuthData object.
+
+    Raises:
+      execptions.NoSuchUserException: If the user of the email does not exist.
+    """
+    auth = cls()
+    auth.email = email
+    if email:
+      auth.user_id = services.user.LookupUserID(
+          cnxn, email, autocreate=autocreate)
+      assert auth.user_id
+      cls._FinishInitialization(cnxn, auth, services, user_pb=None)
+
+    return auth
+
+  @classmethod
+  def FromUserID(cls, cnxn, user_id, services):
+    """Determine auth information for the given user ID.
+
+    Args:
+      cnxn: monorail connection to the database.
+      user_id: int user ID of the user.
+      services: connections to backend servers.
+
+    Returns:
+      A new AuthData object.
+    """
+    auth = cls()
+    auth.user_id = user_id
+    if auth.user_id:
+      auth.email = services.user.LookupUserEmail(cnxn, user_id)
+      cls._FinishInitialization(cnxn, auth, services, user_pb=None)
+
+    return auth
+
+  @classmethod
+  def FromUser(cls, cnxn, user, services):
+    """Determine auth information for the given user.
+
+    Args:
+      cnxn: monorail connection to the database.
+      user: user protobuf.
+      services: connections to backend servers.
+
+    Returns:
+      A new AuthData object.
+    """
+    auth = cls()
+    auth.user_id = user.user_id
+    if auth.user_id:
+      auth.email = user.email
+      cls._FinishInitialization(cnxn, auth, services, user)
+
+    return auth
+
+
+  @classmethod
+  def _FinishInitialization(cls, cnxn, auth, services, user_pb=None):
+    """Fill in the test of the fields based on the user_id."""
+    effective_ids_dict = framework_bizobj.GetEffectiveIds(
+        cnxn, services, [auth.user_id])
+    auth.effective_ids = effective_ids_dict[auth.user_id]
+    auth.user_pb = user_pb or services.user.GetUser(cnxn, auth.user_id)
+    if auth.user_pb:
+      auth.user_view = framework_views.UserView(auth.user_pb)
+
+  def __repr__(self):
+    """Return a string more useful for debugging."""
+    return 'AuthData(email=%r, user_id=%r, effective_ids=%r)' % (
+        self.email, self.user_id, self.effective_ids)