Merge branch 'master' into fix_build

This commit is contained in:
yackob03 2014-01-02 14:33:23 -05:00
commit 96fdae4f0d
23 changed files with 1323 additions and 692 deletions

View file

@ -12,7 +12,7 @@ from collections import defaultdict
from data import model
from data.queue import dockerfile_build_queue
from data.plans import USER_PLANS, BUSINESS_PLANS, get_plan
from data.plans import PLANS, get_plan
from app import app
from util.email import send_confirmation_email, send_recovery_email
from util.names import parse_repository_name, format_robot_username
@ -26,19 +26,53 @@ from auth.permissions import (ReadRepositoryPermission,
OrganizationMemberPermission,
ViewTeamPermission)
from endpoints import registry
from endpoints.web import common_login
from endpoints.common import common_login
from util.cache import cache_control
from datetime import datetime, timedelta
store = app.config['STORAGE']
user_files = app.config['USERFILES']
logger = logging.getLogger(__name__)
route_data = None
def get_route_data():
global route_data
if route_data:
return route_data
routes = []
for rule in app.url_map.iter_rules():
if rule.rule.startswith('/api/'):
endpoint_method = globals()[rule.endpoint]
is_internal = '__internal_call' in dir(endpoint_method)
is_org_api = '__user_call' in dir(endpoint_method)
methods = list(rule.methods.difference(['HEAD', 'OPTIONS']))
route = {
'name': rule.endpoint,
'methods': methods,
'path': rule.rule,
'parameters': list(rule.arguments)
}
if is_org_api:
route['user_method'] = endpoint_method.__user_call
routes.append(route)
route_data = {
'endpoints': routes
}
return route_data
def log_action(kind, user_or_orgname, metadata={}, repo=None):
performer = current_user.db_user()
model.log_action(kind, user_or_orgname, performer=performer, ip=request.remote_addr,
metadata=metadata, repository=repo)
model.log_action(kind, user_or_orgname, performer=performer,
ip=request.remote_addr, metadata=metadata, repository=repo)
def api_login_required(f):
@wraps(f)
@ -58,26 +92,51 @@ def api_login_required(f):
return decorated_view
def internal_api_call(f):
@wraps(f)
def decorated_view(*args, **kwargs):
return f(*args, **kwargs)
decorated_view.__internal_call = True
return decorated_view
def org_api_call(user_call_name):
def internal_decorator(f):
@wraps(f)
def decorated_view(*args, **kwargs):
return f(*args, **kwargs)
decorated_view.__user_call = user_call_name
return decorated_view
return internal_decorator
@app.errorhandler(model.DataModelException)
def handle_dme(ex):
return make_response(ex.message, 400)
@app.errorhandler(KeyError)
def handle_dme(ex):
def handle_dme_key_error(ex):
return make_response(ex.message, 400)
@app.route('/api/discovery')
def discovery():
return jsonify(get_route_data())
@app.route('/api/')
@internal_api_call
def welcome():
return make_response('welcome', 200)
@app.route('/api/plans/')
def plans_list():
def list_plans():
return jsonify({
'user': USER_PLANS,
'business': BUSINESS_PLANS,
'plans': PLANS,
})
@ -107,6 +166,7 @@ def user_view(user):
@app.route('/api/user/', methods=['GET'])
@internal_api_call
def get_logged_in_user():
if current_user.is_anonymous():
return jsonify({'anonymous': True})
@ -120,6 +180,7 @@ def get_logged_in_user():
@app.route('/api/user/private', methods=['GET'])
@api_login_required
@internal_api_call
def get_user_private_count():
user = current_user.db_user()
private_repos = model.get_private_repo_count(user.username)
@ -140,6 +201,7 @@ def get_user_private_count():
@app.route('/api/user/convert', methods=['POST'])
@api_login_required
@internal_api_call
def convert_user_to_organization():
user = current_user.db_user()
convert_data = request.get_json()
@ -164,7 +226,7 @@ def convert_user_to_organization():
# Subscribe the organization to the new plan.
plan = convert_data['plan']
subscribe(user, plan, None, BUSINESS_PLANS)
subscribe(user, plan, None, True) # Require business plans
# Convert the user to an organization.
model.convert_user_to_organization(user, model.get_user(admin_username))
@ -172,11 +234,11 @@ def convert_user_to_organization():
# And finally login with the admin credentials.
return conduct_signin(admin_username, admin_password)
@app.route('/api/user/', methods=['PUT'])
@api_login_required
@internal_api_call
def change_user_details():
user = current_user.db_user()
@ -203,7 +265,8 @@ def change_user_details():
@app.route('/api/user/', methods=['POST'])
def create_user_api():
@internal_api_call
def create_new_user():
user_data = request.get_json()
existing_user = model.get_user(user_data['username'])
@ -229,7 +292,8 @@ def create_user_api():
@app.route('/api/signin', methods=['POST'])
def signin_api():
@internal_api_call
def signin_user():
signin_data = request.get_json()
username = signin_data['username']
@ -263,6 +327,7 @@ def conduct_signin(username, password):
@app.route("/api/signout", methods=['POST'])
@api_login_required
@internal_api_call
def logout():
logout_user()
identity_changed.send(app, identity=AnonymousIdentity())
@ -270,7 +335,8 @@ def logout():
@app.route("/api/recovery", methods=['POST'])
def send_recovery():
@internal_api_call
def request_recovery_email():
email = request.get_json()['email']
code = model.create_reset_password_email_code(email)
send_recovery_email(email, code.code)
@ -355,7 +421,8 @@ def team_view(orgname, team):
@app.route('/api/organization/', methods=['POST'])
@api_login_required
def create_organization_api():
@internal_api_call
def create_organization():
org_data = request.get_json()
existing = None
@ -419,6 +486,7 @@ def get_organization(orgname):
@app.route('/api/organization/<orgname>', methods=['PUT'])
@api_login_required
@org_api_call('change_user_details')
def change_organization_details(orgname):
permission = AdministerOrganizationPermission(orgname)
if permission.can():
@ -427,7 +495,7 @@ def change_organization_details(orgname):
except model.InvalidOrganizationException:
abort(404)
org_data = request.get_json();
org_data = request.get_json()
if 'invoice_email' in org_data:
logger.debug('Changing invoice_email for organization: %s', org.username)
model.change_invoice_email(org, org_data['invoice_email'])
@ -477,7 +545,7 @@ def get_organization_member(orgname, membername):
abort(404)
member_dict = None
member_teams = model.get_organization_members_with_teams(org, membername = membername)
member_teams = model.get_organization_members_with_teams(org, membername=membername)
for member in member_teams:
if not member_dict:
member_dict = {'username': member.user.username,
@ -496,6 +564,7 @@ def get_organization_member(orgname, membername):
@app.route('/api/organization/<orgname>/private', methods=['GET'])
@api_login_required
@internal_api_call
def get_organization_private_allowed(orgname):
permission = CreateRepositoryPermission(orgname)
if permission.can():
@ -551,17 +620,20 @@ def update_organization_team(orgname, teamname):
log_action('org_create_team', orgname, {'team': teamname})
if is_existing:
if 'description' in details and team.description != details['description']:
if ('description' in details and
team.description != details['description']):
team.description = details['description']
team.save()
log_action('org_set_team_description', orgname, {'team': teamname, 'description': team.description})
log_action('org_set_team_description', orgname,
{'team': teamname, 'description': team.description})
if 'role' in details:
role = model.get_team_org_role(team).name
if role != details['role']:
team = model.set_team_org_permission(team, details['role'],
current_user.db_user().username)
log_action('org_set_team_role', orgname, {'team': teamname, 'role': details['role']})
log_action('org_set_team_role', orgname,
{'team': teamname, 'role': details['role']})
resp = jsonify(team_view(orgname, team))
if not is_existing:
@ -629,7 +701,8 @@ def update_organization_team_member(orgname, teamname, membername):
# Add the user to the team.
model.add_user_to_team(user, team)
log_action('org_add_team_member', orgname, {'member': membername, 'team': teamname})
log_action('org_add_team_member', orgname,
{'member': membername, 'team': teamname})
return jsonify(member_view(user))
abort(403)
@ -644,7 +717,8 @@ def delete_organization_team_member(orgname, teamname, membername):
# Remote the user from the team.
invoking_user = current_user.db_user().username
model.remove_user_from_team(orgname, teamname, membername, invoking_user)
log_action('org_remove_team_member', orgname, {'member': membername, 'team': teamname})
log_action('org_remove_team_member', orgname,
{'member': membername, 'team': teamname})
return make_response('Deleted', 204)
abort(403)
@ -652,7 +726,7 @@ def delete_organization_team_member(orgname, teamname, membername):
@app.route('/api/repository', methods=['POST'])
@api_login_required
def create_repo_api():
def create_repo():
owner = current_user.db_user()
req = request.get_json()
namespace_name = req['namespace'] if 'namespace' in req else owner.username
@ -673,7 +747,9 @@ def create_repo_api():
repo.description = req['description']
repo.save()
log_action('create_repo', namespace_name, {'repo': repository_name, 'namespace': namespace_name}, repo=repo)
log_action('create_repo', namespace_name,
{'repo': repository_name, 'namespace': namespace_name},
repo=repo)
return jsonify({
'namespace': namespace_name,
'name': repository_name
@ -683,7 +759,7 @@ def create_repo_api():
@app.route('/api/find/repository', methods=['GET'])
def match_repos_api():
def find_repos():
prefix = request.args.get('query', '')
def repo_view(repo):
@ -706,7 +782,7 @@ def match_repos_api():
@app.route('/api/repository/', methods=['GET'])
def list_repos_api():
def list_repos():
def repo_view(repo_obj):
return {
'namespace': repo_obj.namespace,
@ -749,7 +825,7 @@ def list_repos_api():
@app.route('/api/repository/<path:repository>', methods=['PUT'])
@api_login_required
@parse_repository_name
def update_repo_api(namespace, repository):
def update_repo(namespace, repository):
permission = ModifyRepositoryPermission(namespace, repository)
if permission.can():
repo = model.get_repository(namespace, repository)
@ -758,7 +834,8 @@ def update_repo_api(namespace, repository):
repo.description = values['description']
repo.save()
log_action('set_repo_description', namespace, {'repo': repository, 'description': values['description']},
log_action('set_repo_description', namespace,
{'repo': repository, 'description': values['description']},
repo=repo)
return jsonify({
'success': True
@ -771,14 +848,15 @@ def update_repo_api(namespace, repository):
methods=['POST'])
@api_login_required
@parse_repository_name
def change_repo_visibility_api(namespace, repository):
def change_repo_visibility(namespace, repository):
permission = AdministerRepositoryPermission(namespace, repository)
if permission.can():
repo = model.get_repository(namespace, repository)
if repo:
values = request.get_json()
model.set_repository_visibility(repo, values['visibility'])
log_action('change_repo_visibility', namespace, {'repo': repository, 'visibility': values['visibility']},
log_action('change_repo_visibility', namespace,
{'repo': repository, 'visibility': values['visibility']},
repo=repo)
return jsonify({
'success': True
@ -795,7 +873,8 @@ def delete_repository(namespace, repository):
if permission.can():
model.purge_repository(namespace, repository)
registry.delete_repository_storage(namespace, repository)
log_action('delete_repo', namespace, {'repo': repository, 'namespace': namespace})
log_action('delete_repo', namespace,
{'repo': repository, 'namespace': namespace})
return make_response('Deleted', 204)
abort(403)
@ -813,7 +892,7 @@ def image_view(image):
@app.route('/api/repository/<path:repository>', methods=['GET'])
@parse_repository_name
def get_repo_api(namespace, repository):
def get_repo(namespace, repository):
logger.debug('Get repo: %s/%s' % (namespace, repository))
def tag_view(tag):
@ -912,7 +991,8 @@ def request_repo_build(namespace, repository):
dockerfile_build_queue.put(json.dumps({'build_id': build_request.id}))
log_action('build_dockerfile', namespace,
{'repo': repository, 'namespace': namespace, 'fileid': dockerfile_id}, repo=repo)
{'repo': repository, 'namespace': namespace,
'fileid': dockerfile_id}, repo=repo)
resp = jsonify({
'started': True
@ -943,7 +1023,8 @@ def create_webhook(namespace, repository):
resp.headers['Location'] = url_for('get_webhook', repository=repo_string,
public_id=webhook.public_id)
log_action('add_repo_webhook', namespace,
{'repo': repository, 'webhook_id': webhook.public_id}, repo=repo)
{'repo': repository, 'webhook_id': webhook.public_id},
repo=repo)
return resp
abort(403) # Permissions denied
@ -994,6 +1075,7 @@ def delete_webhook(namespace, repository, public_id):
@app.route('/api/filedrop/', methods=['POST'])
@api_login_required
@internal_api_call
def get_filedrop_url():
mime_type = request.get_json()['mimeType']
(url, file_id) = user_files.prepare_for_drop(mime_type)
@ -1143,7 +1225,8 @@ def list_repo_user_permissions(namespace, repository):
current_func = role_view_func
def wrapped_role_org_view(repo_perm):
return wrap_role_view_org(current_func(repo_perm), repo_perm.user, org_members)
return wrap_role_view_org(current_func(repo_perm), repo_perm.user,
org_members)
role_view_func = wrapped_role_org_view
@ -1228,7 +1311,8 @@ def change_user_permissions(namespace, repository, username):
return error_resp
log_action('change_repo_permission', namespace,
{'username': username, 'repo': repository, 'role': new_permission['role']},
{'username': username, 'repo': repository,
'role': new_permission['role']},
repo=model.get_repository(namespace, repository))
resp = jsonify(perm_view)
@ -1255,7 +1339,8 @@ def change_team_permissions(namespace, repository, teamname):
new_permission['role'])
log_action('change_repo_permission', namespace,
{'team': teamname, 'repo': repository, 'role': new_permission['role']},
{'team': teamname, 'repo': repository,
'role': new_permission['role']},
repo=model.get_repository(namespace, repository))
resp = jsonify(role_view(perm))
@ -1282,7 +1367,8 @@ def delete_user_permissions(namespace, repository, username):
error_resp.status_code = 400
return error_resp
log_action('delete_repo_permission', namespace, {'username': username, 'repo': repository},
log_action('delete_repo_permission', namespace,
{'username': username, 'repo': repository},
repo=model.get_repository(namespace, repository))
return make_response('Deleted', 204)
@ -1299,7 +1385,8 @@ def delete_team_permissions(namespace, repository, teamname):
if permission.can():
model.delete_team_permission(teamname, namespace, repository)
log_action('delete_repo_permission', namespace, {'team': teamname, 'repo': repository},
log_action('delete_repo_permission', namespace,
{'team': teamname, 'repo': repository},
repo=model.get_repository(namespace, repository))
return make_response('Deleted', 204)
@ -1353,7 +1440,8 @@ def create_token(namespace, repository):
token = model.create_delegate_token(namespace, repository,
token_params['friendlyName'])
log_action('add_repo_accesstoken', namespace, {'repo': repository, 'token': token_params['friendlyName']},
log_action('add_repo_accesstoken', namespace,
{'repo': repository, 'token': token_params['friendlyName']},
repo = model.get_repository(namespace, repository))
resp = jsonify(token_view(token))
@ -1378,7 +1466,8 @@ def change_token(namespace, repository, code):
new_permission['role'])
log_action('change_repo_permission', namespace,
{'repo': repository, 'token': token.friendly_name, 'code': code, 'role': new_permission['role']},
{'repo': repository, 'token': token.friendly_name, 'code': code,
'role': new_permission['role']},
repo = model.get_repository(namespace, repository))
resp = jsonify(token_view(token))
@ -1397,7 +1486,8 @@ def delete_token(namespace, repository, code):
token = model.delete_delegate_token(namespace, repository, code)
log_action('delete_repo_accesstoken', namespace,
{'repo': repository, 'token': token.friendly_name, 'code': code},
{'repo': repository, 'token': token.friendly_name,
'code': code},
repo = model.get_repository(namespace, repository))
return make_response('Deleted', 204)
@ -1416,14 +1506,17 @@ def subscription_view(stripe_subscription, used_repos):
@app.route('/api/user/card', methods=['GET'])
@api_login_required
def get_user_card_api():
@internal_api_call
def get_user_card():
user = current_user.db_user()
return get_card(user)
@app.route('/api/organization/<orgname>/card', methods=['GET'])
@api_login_required
def get_org_card_api(orgname):
@internal_api_call
@org_api_call('get_user_card')
def get_org_card(orgname):
permission = AdministerOrganizationPermission(orgname)
if permission.can():
organization = model.get_organization(orgname)
@ -1434,7 +1527,8 @@ def get_org_card_api(orgname):
@app.route('/api/user/card', methods=['POST'])
@api_login_required
def set_user_card_api():
@internal_api_call
def set_user_card():
user = current_user.db_user()
token = request.get_json()['token']
response = set_card(user, token)
@ -1444,7 +1538,8 @@ def set_user_card_api():
@app.route('/api/organization/<orgname>/card', methods=['POST'])
@api_login_required
def set_org_card_api(orgname):
@org_api_call('set_user_card')
def set_org_card(orgname):
permission = AdministerOrganizationPermission(orgname)
if permission.can():
organization = model.get_organization(orgname)
@ -1486,21 +1581,22 @@ def get_card(user):
if default_card:
card_info = {
'owner': card.name,
'type': card.type,
'last4': card.last4
'owner': default_card.name,
'type': default_card.type,
'last4': default_card.last4
}
return jsonify({'card': card_info})
@app.route('/api/user/plan', methods=['PUT'])
@api_login_required
def subscribe_api():
@internal_api_call
def update_user_subscription():
request_data = request.get_json()
plan = request_data['plan']
token = request_data['token'] if 'token' in request_data else None
user = current_user.db_user()
return subscribe(user, plan, token, USER_PLANS)
return subscribe(user, plan, token, False) # Business features not required
def carderror_response(e):
@ -1511,15 +1607,22 @@ def carderror_response(e):
return resp
def subscribe(user, plan, token, accepted_plans):
def subscribe(user, plan, token, require_business_plan):
plan_found = None
for plan_obj in accepted_plans:
for plan_obj in PLANS:
if plan_obj['stripeId'] == plan:
plan_found = plan_obj
if not plan_found:
if not plan_found or plan_found['deprecated']:
logger.warning('Plan not found or deprecated: %s', plan)
abort(404)
if (require_business_plan and not plan_found['bus_features'] and not
plan_found['price'] == 0):
logger.warning('Business attempting to subscribe to personal plan: %s',
user.username)
abort(400)
private_repos = model.get_private_repo_count(user.username)
# This is the default response
@ -1578,9 +1681,32 @@ def subscribe(user, plan, token, accepted_plans):
return resp
@app.route('/api/user/invoices', methods=['GET'])
@api_login_required
def list_user_invoices():
user = current_user.db_user()
if not user.stripe_id:
abort(404)
return get_invoices(user.stripe_id)
@app.route('/api/organization/<orgname>/invoices', methods=['GET'])
@api_login_required
def org_invoices_api(orgname):
@org_api_call('list_user_invoices')
def list_org_invoices(orgname):
permission = AdministerOrganizationPermission(orgname)
if permission.can():
organization = model.get_organization(orgname)
if not organization.stripe_id:
abort(404)
return get_invoices(organization.stripe_id)
abort(403)
def get_invoices(customer_id):
def invoice_view(i):
return {
'id': i.id,
@ -1596,37 +1722,32 @@ def org_invoices_api(orgname):
'plan': i.lines.data[0].plan.id if i.lines.data[0].plan else None
}
permission = AdministerOrganizationPermission(orgname)
if permission.can():
organization = model.get_organization(orgname)
if not organization.stripe_id:
abort(404)
invoices = stripe.Invoice.all(customer=organization.stripe_id, count=12)
return jsonify({
'invoices': [invoice_view(i) for i in invoices.data]
})
abort(403)
invoices = stripe.Invoice.all(customer=customer_id, count=12)
return jsonify({
'invoices': [invoice_view(i) for i in invoices.data]
})
@app.route('/api/organization/<orgname>/plan', methods=['PUT'])
@api_login_required
def subscribe_org_api(orgname):
@internal_api_call
@org_api_call('update_user_subscription')
def update_org_subscription(orgname):
permission = AdministerOrganizationPermission(orgname)
if permission.can():
request_data = request.get_json()
plan = request_data['plan']
token = request_data['token'] if 'token' in request_data else None
organization = model.get_organization(orgname)
return subscribe(organization, plan, token, BUSINESS_PLANS)
return subscribe(organization, plan, token, True) # Business plan required
abort(403)
@app.route('/api/user/plan', methods=['GET'])
@api_login_required
def get_subscription():
@internal_api_call
def get_user_subscription():
user = current_user.db_user()
private_repos = model.get_private_repo_count(user.username)
@ -1644,6 +1765,8 @@ def get_subscription():
@app.route('/api/organization/<orgname>/plan', methods=['GET'])
@api_login_required
@internal_api_call
@org_api_call('get_user_subscription')
def get_org_subscription(orgname):
permission = AdministerOrganizationPermission(orgname)
if permission.can():
@ -1656,7 +1779,7 @@ def get_org_subscription(orgname):
return jsonify(subscription_view(cus.subscription, private_repos))
return jsonify({
'plan': 'bus-free',
'plan': 'free',
'usedPrivateRepos': private_repos,
})
@ -1682,6 +1805,7 @@ def get_user_robots():
@app.route('/api/organization/<orgname>/robots', methods=['GET'])
@api_login_required
@org_api_call('get_user_robots')
def get_org_robots(orgname):
permission = OrganizationMemberPermission(orgname)
if permission.can():
@ -1695,7 +1819,7 @@ def get_org_robots(orgname):
@app.route('/api/user/robots/<robot_shortname>', methods=['PUT'])
@api_login_required
def create_robot(robot_shortname):
def create_user_robot(robot_shortname):
parent = current_user.db_user()
robot, password = model.create_robot(robot_shortname, parent)
resp = jsonify(robot_view(robot.username, password))
@ -1707,6 +1831,7 @@ def create_robot(robot_shortname):
@app.route('/api/organization/<orgname>/robots/<robot_shortname>',
methods=['PUT'])
@api_login_required
@org_api_call('create_user_robot')
def create_org_robot(orgname, robot_shortname):
permission = AdministerOrganizationPermission(orgname)
if permission.can():
@ -1722,7 +1847,7 @@ def create_org_robot(orgname, robot_shortname):
@app.route('/api/user/robots/<robot_shortname>', methods=['DELETE'])
@api_login_required
def delete_robot(robot_shortname):
def delete_user_robot(robot_shortname):
parent = current_user.db_user()
model.delete_robot(format_robot_username(parent.username, robot_shortname))
log_action('delete_robot', parent.username, {'robot': robot_shortname})
@ -1732,6 +1857,7 @@ def delete_robot(robot_shortname):
@app.route('/api/organization/<orgname>/robots/<robot_shortname>',
methods=['DELETE'])
@api_login_required
@org_api_call('delete_user_robot')
def delete_org_robot(orgname, robot_shortname):
permission = AdministerOrganizationPermission(orgname)
if permission.can():
@ -1743,27 +1869,27 @@ def delete_org_robot(orgname, robot_shortname):
def log_view(log):
view = {
'kind': log.kind.name,
'metadata': json.loads(log.metadata_json),
'ip': log.ip,
'datetime': log.datetime,
view = {
'kind': log.kind.name,
'metadata': json.loads(log.metadata_json),
'ip': log.ip,
'datetime': log.datetime,
}
if log.performer:
view['performer'] = {
'username': log.performer.username,
'is_robot': log.performer.robot,
}
if log.performer:
view['performer'] = {
'username': log.performer.username,
'is_robot': log.performer.robot,
}
return view
return view
@app.route('/api/repository/<path:repository>/logs', methods=['GET'])
@api_login_required
@parse_repository_name
def repo_logs_api(namespace, repository):
def list_repo_logs(namespace, repository):
permission = AdministerRepositoryPermission(namespace, repository)
if permission.can():
repo = model.get_repository(namespace, repository)
@ -1779,19 +1905,33 @@ def repo_logs_api(namespace, repository):
@app.route('/api/organization/<orgname>/logs', methods=['GET'])
@api_login_required
def org_logs_api(orgname):
@org_api_call('list_user_logs')
def list_org_logs(orgname):
permission = AdministerOrganizationPermission(orgname)
if permission.can():
performer_name = request.args.get('performer', None)
start_time = request.args.get('starttime', None)
end_time = request.args.get('endtime', None)
return get_logs(orgname, start_time, end_time, performer_name=performer_name)
return get_logs(orgname, start_time, end_time,
performer_name=performer_name)
abort(403)
def get_logs(namespace, start_time, end_time, performer_name=None, repository=None):
@app.route('/api/user/logs', methods=['GET'])
@api_login_required
def list_user_logs():
performer_name = request.args.get('performer', None)
start_time = request.args.get('starttime', None)
end_time = request.args.get('endtime', None)
return get_logs(current_user.db_user().username, start_time, end_time,
performer_name=performer_name)
def get_logs(namespace, start_time, end_time, performer_name=None,
repository=None):
performer = None
if performer_name:
performer = model.get_user(performer_name)
@ -1815,7 +1955,8 @@ def get_logs(namespace, start_time, end_time, performer_name=None, repository=No
if not end_time:
end_time = datetime.today()
logs = model.list_logs(namespace, start_time, end_time, performer = performer, repository=repository)
logs = model.list_logs(namespace, start_time, end_time, performer=performer,
repository=repository)
return jsonify({
'start_time': start_time,
'end_time': end_time,