This repository has been archived on 2020-03-24. You can view files and clone it, but cannot push or open issues or pull requests.
quay/auth/validateresult.py
Joseph Schorr 651666b60b Refactor our auth handling code to be cleaner
Breaks out the validation code from the auth context modification calls, makes decorators easier to define and adds testing for each individual piece. Will be the basis of better error messaging in the following change.
2017-03-23 15:42:45 -04:00

101 lines
3.1 KiB
Python

from enum import Enum
from flask_principal import Identity, identity_changed
from app import app
from auth.auth_context import (set_authenticated_user, set_validated_token, set_grant_context,
set_validated_oauth_token)
from auth.scopes import scopes_from_scope_string
from auth.permissions import QuayDeferredPermissionUser
class AuthKind(Enum):
cookie = 'cookie'
basic = 'basic'
oauth = 'oauth'
signed_grant = 'signed_grant'
class ValidateResult(object):
""" A result of validating auth in one form or another. """
def __init__(self, kind, missing=False, user=None, token=None, oauthtoken=None,
robot=None, signed_data=None, error_message=None):
self.kind = kind
self.missing = missing
self.user = user
self.robot = robot
self.token = token
self.oauthtoken = oauthtoken
self.signed_data = signed_data
self.error_message = error_message
def tuple(self):
return (self.kind, self.missing, self.user, self.token, self.oauthtoken, self.robot,
self.signed_data, self.error_message)
def __eq__(self, other):
return self.tuple() == other.tuple()
def apply_to_context(self):
""" Applies this auth result to the auth context and Flask-Principal. """
# Set the various pieces of the auth context.
if self.oauthtoken:
set_authenticated_user(self.authed_user)
set_validated_oauth_token(self.oauthtoken)
elif self.authed_user:
set_authenticated_user(self.authed_user)
elif self.token:
set_validated_token(self.token)
elif self.signed_data:
if self.signed_data['user_context']:
set_grant_context({
'user': self.signed_data['user_context'],
'kind': 'user',
})
# Set the identity for Flask-Principal.
if self.identity:
identity_changed.send(app, identity=self.identity)
@property
def authed_user(self):
""" Returns the authenticated user, whether directly, or via an OAuth token. """
if not self.auth_valid:
return None
if self.oauthtoken:
return self.oauthtoken.authorized_user
return self.user if self.user else self.robot
@property
def identity(self):
""" Returns the identity for the auth result. """
if not self.auth_valid:
return None
if self.oauthtoken:
scope_set = scopes_from_scope_string(self.oauthtoken.scope)
return QuayDeferredPermissionUser.for_user(self.oauthtoken.authorized_user, scope_set)
if self.authed_user:
return QuayDeferredPermissionUser.for_user(self.authed_user)
if self.token:
return Identity(self.token.code, 'token')
if self.signed_data:
identity = Identity(None, 'signed_grant')
identity.provides.update(self.signed_data['grants'])
return identity
return None
@property
def has_user(self):
""" Returns whether a user (not a robot) was authenticated successfully. """
return bool(self.user)
@property
def auth_valid(self):
""" Returns whether authentication successfully occurred. """
return self.user or self.token or self.oauthtoken or self.robot or self.signed_data