Add support for metadata on robot accounts
Fixes https://jira.coreos.com/browse/QUAY-847 Fixes https://jira.coreos.com/browse/QUAY-816
This commit is contained in:
parent
a693771345
commit
254cdfe43a
8 changed files with 229 additions and 52 deletions
|
@ -14,7 +14,8 @@ from data.database import (User, LoginService, FederatedLogin, RepositoryPermiss
|
|||
EmailConfirmation, Role, db_for_update, random_string_generator,
|
||||
UserRegion, ImageStorageLocation,
|
||||
ServiceKeyApproval, OAuthApplication, RepositoryBuildTrigger,
|
||||
UserPromptKind, UserPrompt, UserPromptTypes, DeletedNamespace)
|
||||
UserPromptKind, UserPrompt, UserPromptTypes, DeletedNamespace,
|
||||
RobotAccountMetadata)
|
||||
from data.model import (DataModelException, InvalidPasswordException, InvalidRobotException,
|
||||
InvalidUsernameException, InvalidEmailAddressException,
|
||||
TooManyLoginAttemptsException, db_transaction,
|
||||
|
@ -231,7 +232,7 @@ def update_enabled(user, set_enabled):
|
|||
user.save()
|
||||
|
||||
|
||||
def create_robot(robot_shortname, parent):
|
||||
def create_robot(robot_shortname, parent, description='', unstructured_metadata=None):
|
||||
(username_valid, username_issue) = validate_username(robot_shortname)
|
||||
if not username_valid:
|
||||
raise InvalidRobotException('The name for the robot \'%s\' is invalid: %s' %
|
||||
|
@ -245,33 +246,59 @@ def create_robot(robot_shortname, parent):
|
|||
msg = 'Existing robot with name: %s' % username
|
||||
logger.info(msg)
|
||||
raise InvalidRobotException(msg)
|
||||
|
||||
except User.DoesNotExist:
|
||||
pass
|
||||
|
||||
service = LoginService.get(name='quayrobot')
|
||||
try:
|
||||
created = User.create(username=username, robot=True)
|
||||
with db_transaction():
|
||||
created = User.create(username=username, robot=True)
|
||||
password = created.email
|
||||
|
||||
service = LoginService.get(name='quayrobot')
|
||||
password = created.email
|
||||
FederatedLogin.create(user=created, service=service,
|
||||
service_ident=password)
|
||||
|
||||
return created, password
|
||||
FederatedLogin.create(user=created, service=service, service_ident=password)
|
||||
RobotAccountMetadata.create(robot_account=created, description=description[0:255],
|
||||
unstructured_json=unstructured_metadata or {})
|
||||
return created, password
|
||||
except Exception as ex:
|
||||
raise DataModelException(ex.message)
|
||||
|
||||
|
||||
def get_or_create_robot_metadata(robot):
|
||||
try:
|
||||
return RobotAccountMetadata.get(robot_account=robot)
|
||||
except RobotAccountMetadata.DoesNotExist:
|
||||
try:
|
||||
return RobotAccountMetadata.create(robot_account=robot, description='',
|
||||
unstructured_json='{}')
|
||||
except IntegrityError:
|
||||
return RobotAccountMetadata.get(robot_account=robot)
|
||||
|
||||
|
||||
def update_robot_metadata(robot, description='', unstructured_json=None):
|
||||
""" Updates the description and user-specified unstructured metadata associated
|
||||
with a robot account to that specified. """
|
||||
metadata = get_or_create_robot_metadata(robot)
|
||||
metadata.description = description
|
||||
metadata.unstructured_json = unstructured_json or metadata.unstructured_json or {}
|
||||
metadata.save()
|
||||
|
||||
|
||||
def get_robot(robot_shortname, parent):
|
||||
robot_username = format_robot_username(parent.username, robot_shortname)
|
||||
robot = lookup_robot(robot_username)
|
||||
return robot, robot.email
|
||||
|
||||
|
||||
def get_robot_and_metadata(robot_shortname, parent):
|
||||
robot_username = format_robot_username(parent.username, robot_shortname)
|
||||
robot, metadata = lookup_robot_and_metadata(robot_username)
|
||||
return robot, robot.email, metadata
|
||||
|
||||
|
||||
def lookup_robot(robot_username):
|
||||
try:
|
||||
return (User
|
||||
.select()
|
||||
.select(User, FederatedLogin)
|
||||
.join(FederatedLogin)
|
||||
.join(LoginService)
|
||||
.where(LoginService.name == 'quayrobot', User.username == robot_username,
|
||||
|
@ -281,6 +308,11 @@ def lookup_robot(robot_username):
|
|||
raise InvalidRobotException('Could not find robot with username: %s' % robot_username)
|
||||
|
||||
|
||||
def lookup_robot_and_metadata(robot_username):
|
||||
robot = lookup_robot(robot_username)
|
||||
return robot, get_or_create_robot_metadata(robot)
|
||||
|
||||
|
||||
def get_matching_robots(name_prefix, username, limit=10):
|
||||
admined_orgs = (_basequery.get_user_organizations(username)
|
||||
.switch(Team)
|
||||
|
@ -333,7 +365,7 @@ def verify_robot(robot_username, password):
|
|||
def regenerate_robot_token(robot_shortname, parent):
|
||||
robot_username = format_robot_username(parent.username, robot_shortname)
|
||||
|
||||
robot = lookup_robot(robot_username)
|
||||
robot, metadata = lookup_robot_and_metadata(robot_username)
|
||||
password = random_string_generator(length=64)()
|
||||
robot.email = password
|
||||
robot.uuid = str(uuid4())
|
||||
|
@ -345,7 +377,7 @@ def regenerate_robot_token(robot_shortname, parent):
|
|||
login.save()
|
||||
robot.save()
|
||||
|
||||
return robot, password
|
||||
return robot, password, metadata
|
||||
|
||||
def delete_robot(robot_username):
|
||||
try:
|
||||
|
@ -367,15 +399,18 @@ def _list_entity_robots(entity_name):
|
|||
materialized list so that callers can use db_for_update.
|
||||
"""
|
||||
return (User
|
||||
.select()
|
||||
.select(User, FederatedLogin, RobotAccountMetadata)
|
||||
.join(FederatedLogin)
|
||||
.switch(User)
|
||||
.join(RobotAccountMetadata, JOIN_LEFT_OUTER)
|
||||
.where(User.robot == True, User.username ** (entity_name + '+%')))
|
||||
|
||||
|
||||
def list_entity_robot_permission_teams(entity_name, include_permissions=False):
|
||||
query = (_list_entity_robots(entity_name))
|
||||
|
||||
fields = [User.username, User.creation_date, FederatedLogin.service_ident]
|
||||
fields = [User.username, User.creation_date, FederatedLogin.service_ident,
|
||||
RobotAccountMetadata.description, RobotAccountMetadata.unstructured_json]
|
||||
if include_permissions:
|
||||
query = (query
|
||||
.join(RepositoryPermission, JOIN_LEFT_OUTER,
|
||||
|
|
Reference in a new issue