blob: 3c1bee9ac8f12ca046e01c234958dcb243bd4ac8 [file] [log] [blame]
# 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)