from endpoints.api import (resource, nickname, ApiResource, log_action, related_user_resource, Unauthorized, require_user_admin, internal_only, require_scope, path_param) from auth.permissions import AdministerOrganizationPermission, OrganizationMemberPermission from auth.auth_context import get_authenticated_user from auth import scopes from data import model from util.names import format_robot_username from flask import abort def robot_view(name, token, count=None): return { 'name': name, 'token': token, 'permission_count': count } def permission_view(permission): return { 'repository': { 'name': permission.repository.name, 'is_public': permission.repository.visibility.name == 'public' }, 'role': permission.role.name } @resource('/v1/user/robots') @internal_only class UserRobotList(ApiResource): """ Resource for listing user robots. """ @require_user_admin @nickname('getUserRobots') def get(self): """ List the available robots for the user. """ user = get_authenticated_user() robots = model.list_entity_robot_tuples(user.username) return { 'robots': [robot_view(name, password, count) for name, password, count in robots] } @resource('/v1/user/robots/') @path_param('robot_shortname', 'The short name for the robot, without any user or organization prefix') @internal_only class UserRobot(ApiResource): """ Resource for managing a user's robots. """ @require_user_admin @nickname('getUserRobot') def get(self, robot_shortname): """ Returns the user's robot with the specified name. """ parent = get_authenticated_user() robot, password = model.get_robot(robot_shortname, parent) return robot_view(robot.username, password) @require_user_admin @nickname('createUserRobot') def put(self, robot_shortname): """ Create a new user robot with the specified name. """ parent = get_authenticated_user() robot, password = model.create_robot(robot_shortname, parent) log_action('create_robot', parent.username, {'robot': robot_shortname}) return robot_view(robot.username, password), 201 @require_user_admin @nickname('deleteUserRobot') def delete(self, robot_shortname): """ Delete an existing robot. """ parent = get_authenticated_user() model.delete_robot(format_robot_username(parent.username, robot_shortname)) log_action('delete_robot', parent.username, {'robot': robot_shortname}) return 'Deleted', 204 @resource('/v1/organization//robots') @path_param('orgname', 'The name of the organization') @related_user_resource(UserRobotList) class OrgRobotList(ApiResource): """ Resource for listing an organization's robots. """ @require_scope(scopes.ORG_ADMIN) @nickname('getOrgRobots') def get(self, orgname): """ List the organization's robots. """ permission = OrganizationMemberPermission(orgname) if permission.can(): robots = model.list_entity_robot_tuples(orgname) return { 'robots': [robot_view(name, password, count) for name, password, count in robots] } raise Unauthorized() @resource('/v1/organization//robots/') @path_param('orgname', 'The name of the organization') @path_param('robot_shortname', 'The short name for the robot, without any user or organization prefix') @related_user_resource(UserRobot) class OrgRobot(ApiResource): """ Resource for managing an organization's robots. """ @require_scope(scopes.ORG_ADMIN) @nickname('getOrgRobot') def get(self, orgname, robot_shortname): """ Returns the organization's robot with the specified name. """ permission = AdministerOrganizationPermission(orgname) if permission.can(): parent = model.get_organization(orgname) robot, password = model.get_robot(robot_shortname, parent) return robot_view(robot.username, password) raise Unauthorized() @require_scope(scopes.ORG_ADMIN) @nickname('createOrgRobot') def put(self, orgname, robot_shortname): """ Create a new robot in the organization. """ permission = AdministerOrganizationPermission(orgname) if permission.can(): parent = model.get_organization(orgname) robot, password = model.create_robot(robot_shortname, parent) log_action('create_robot', orgname, {'robot': robot_shortname}) return robot_view(robot.username, password), 201 raise Unauthorized() @require_scope(scopes.ORG_ADMIN) @nickname('deleteOrgRobot') def delete(self, orgname, robot_shortname): """ Delete an existing organization robot. """ permission = AdministerOrganizationPermission(orgname) if permission.can(): model.delete_robot(format_robot_username(orgname, robot_shortname)) log_action('delete_robot', orgname, {'robot': robot_shortname}) return 'Deleted', 204 raise Unauthorized() @resource('/v1/user/robots//permissions') @path_param('robot_shortname', 'The short name for the robot, without any user or organization prefix') @internal_only class UserRobotPermissions(ApiResource): """ Resource for listing the permissions a user's robot has in the system. """ @require_user_admin @nickname('getUserRobotPermissions') def get(self, robot_shortname): """ Returns the list of repository permissions for the user's robot. """ parent = get_authenticated_user() robot, password = model.get_robot(robot_shortname, parent) permissions = model.list_robot_permissions(robot.username) return { 'permissions': [permission_view(permission) for permission in permissions] } @resource('/v1/organization//robots//permissions') @path_param('orgname', 'The name of the organization') @path_param('robot_shortname', 'The short name for the robot, without any user or organization prefix') @related_user_resource(UserRobotPermissions) class OrgRobotPermissions(ApiResource): """ Resource for listing the permissions an org's robot has in the system. """ @require_user_admin @nickname('getOrgRobotPermissions') def get(self, orgname, robot_shortname): """ Returns the list of repository permissions for the org's robot. """ permission = AdministerOrganizationPermission(orgname) if permission.can(): parent = model.get_organization(orgname) robot, password = model.get_robot(robot_shortname, parent) permissions = model.list_robot_permissions(robot.username) return { 'permissions': [permission_view(permission) for permission in permissions] } abort(403) @resource('/v1/user/robots//regenerate') @path_param('robot_shortname', 'The short name for the robot, without any user or organization prefix') @internal_only class RegenerateUserRobot(ApiResource): """ Resource for regenerate an organization's robot's token. """ @require_user_admin @nickname('regenerateUserRobotToken') def post(self, robot_shortname): """ Regenerates the token for a user's robot. """ parent = get_authenticated_user() robot, password = model.regenerate_robot_token(robot_shortname, parent) log_action('regenerate_robot_token', parent.username, {'robot': robot_shortname}) return robot_view(robot.username, password) @resource('/v1/organization//robots//regenerate') @path_param('orgname', 'The name of the organization') @path_param('robot_shortname', 'The short name for the robot, without any user or organization prefix') @related_user_resource(RegenerateUserRobot) class RegenerateOrgRobot(ApiResource): """ Resource for regenerate an organization's robot's token. """ @require_scope(scopes.ORG_ADMIN) @nickname('regenerateOrgRobotToken') def post(self, orgname, robot_shortname): """ Regenerates the token for an organization robot. """ permission = AdministerOrganizationPermission(orgname) if permission.can(): parent = model.get_organization(orgname) robot, password = model.regenerate_robot_token(robot_shortname, parent) log_action('regenerate_robot_token', orgname, {'robot': robot_shortname}) return robot_view(robot.username, password) raise Unauthorized()