diff --git a/data/model.py b/data/model.py index 9ef8d8ce9..8a215ad6d 100644 --- a/data/model.py +++ b/data/model.py @@ -96,8 +96,8 @@ def get_token(code): return AccessToken.get(AccessToken.code == code) -def get_matching_repositories(repo_term, username=None): - query = Repository.select().distinct().limit(10).join(Visibility) +def get_visible_repositories(username=None): + query = Repository.select().distinct().join(Visibility) or_clauses = [(Visibility.name == 'public')] if username: @@ -106,12 +106,17 @@ def get_matching_repositories(repo_term, username=None): query = with_perms.join(User) or_clauses.append(User.username == username) + return query.where(reduce(operator.or_, or_clauses)) + + +def get_matching_repositories(repo_term, username=None): + visible = get_visible_repositories(username) search_clauses = (Repository.name ** ('%' + repo_term + '%') | Repository.namespace ** ('%' + repo_term + '%') | Repository.description ** ('%' + repo_term + '%')) - final = query.where(search_clauses).where(reduce(operator.or_, or_clauses)) + final = visible.where(search_clauses).limit(10) return list(final) @@ -144,20 +149,20 @@ def get_all_repo_users(namespace_name, repository_name): Repository.name == repository_name) -def get_repository(namespace, name): +def get_repository(namespace_name, repository_name): try: - return Repository.get(Repository.name == name, - Repository.namespace == namespace) + return Repository.get(Repository.name == repository_name, + Repository.namespace == namespace_name) except Repository.DoesNotExist: return None -def get_user_repositories(user): - select = RepositoryPermission.select(RepositoryPermission, Repository, Role) - with_user = select.join(User).where(User.username == user.username) - with_role = with_user.switch(RepositoryPermission).join(Role) - with_repo = with_role.switch(RepositoryPermission).join(Repository) - return with_repo +def repository_is_public(namespace_name, repository_name): + joined = Repository.select().join(Visibility) + query = joined.where(Repository.namespace == namespace_name, + Repository.name == repository_name, + Visibility.name == 'public') + return len(list(query)) > 0 def create_repository(namespace, name, owner): diff --git a/endpoints/api.py b/endpoints/api.py index 1954f8ff9..14b55ae88 100644 --- a/endpoints/api.py +++ b/endpoints/api.py @@ -76,16 +76,16 @@ def match_repos_api(prefix): @app.route('/api/repository/', methods=['GET']) @login_required def list_repos_api(): - def repo_view(repo_perm): + def repo_view(repo_obj): return { - 'namespace': repo_perm.repository.namespace, - 'name': repo_perm.repository.name, - 'role': repo_perm.role.name, - 'description': repo_perm.repository.description, + 'namespace': repo_obj.namespace, + 'name': repo_obj.name, + 'description': repo_obj.description, } + username = current_user.db_user.username repos = [repo_view(repo) - for repo in model.get_user_repositories(current_user.db_user)] + for repo in model.get_visible_repositories(username)] response = { 'repositories': repos } @@ -136,7 +136,7 @@ def get_repo_api(namespace, repository): } permission = ReadRepositoryPermission(namespace, repository) - if permission.can(): + if permission.can() or model.repository_is_public(namespace, repository): repo = model.get_repository(namespace, repository) if repo: tags = model.list_repository_tags(namespace, repository) @@ -168,7 +168,7 @@ def role_view(repo_perm_obj): @parse_repository_name def list_tag_images(namespace, repository, tag): permission = ReadRepositoryPermission(namespace, repository) - if permission.can(): + if permission.can() or model.repository_is_public(namespace, repository): images = model.get_tag_images(namespace, repository, tag) return jsonify({ diff --git a/endpoints/index.py b/endpoints/index.py index 4fb52cb7f..e6708ed6e 100644 --- a/endpoints/index.py +++ b/endpoints/index.py @@ -157,7 +157,7 @@ def get_repository_images(namespace, repository): # TODO invalidate token? - if permission.can(): + if permission.can() or model.repository_is_public(namespace, repository): all_images = [] for image in model.get_repository_images(namespace, repository): new_image_view = { diff --git a/endpoints/registry.py b/endpoints/registry.py index 7dfb74667..e1bdc6d42 100644 --- a/endpoints/registry.py +++ b/endpoints/registry.py @@ -80,14 +80,14 @@ def set_cache_headers(f): @set_cache_headers def get_image_layer(namespace, repository, image_id, headers): permission = ReadRepositoryPermission(namespace, repository) - if not permission.can(): - abort(403) + if permission.can() or model.repository_is_public(namespace, repository): + try: + return Response(store.stream_read(store.image_layer_path( + namespace, repository, image_id)), headers=headers) + except IOError: + abort(404) #'Image not found', 404) - try: - return Response(store.stream_read(store.image_layer_path( - namespace, repository, image_id)), headers=headers) - except IOError: - abort(404) #'Image not found', 404) + abort(403) @app.route('/v1/images//layer', methods=['PUT']) @@ -182,7 +182,8 @@ def put_image_checksum(namespace, repository, image_id): @set_cache_headers def get_image_json(namespace, repository, image_id, headers): permission = ReadRepositoryPermission(namespace, repository) - if not permission.can(): + if (not permission.can() and not + model.repository_is_public(namespace, repository)): abort(403) try: @@ -211,7 +212,8 @@ def get_image_json(namespace, repository, image_id, headers): @set_cache_headers def get_image_ancestry(namespace, repository, image_id, headers): permission = ReadRepositoryPermission(namespace, repository) - if not permission.can(): + if (not permission.can() and not + model.repository_is_public(namespace, repository)): abort(403) try: diff --git a/endpoints/tags.py b/endpoints/tags.py index 89cbdc442..46d64a985 100644 --- a/endpoints/tags.py +++ b/endpoints/tags.py @@ -25,7 +25,7 @@ logger = logging.getLogger(__name__) def get_tags(namespace, repository): permission = ReadRepositoryPermission(namespace, repository) - if permission.can(): + if permission.can() or model.repository_is_public(namespace, repository): tags = model.list_repository_tags(namespace, repository) tag_map = {tag.name: tag.image.image_id for tag in tags} return jsonify(tag_map) @@ -40,7 +40,7 @@ def get_tags(namespace, repository): def get_tag(namespace, repository, tag): permission = ReadRepositoryPermission(namespace, repository) - if permission.can(): + if permission.can() or model.repository_is_public(namespace, repository): tag_image = model.get_tag_image(namespace, repository, tag) response = make_response(tag_image.image_id, 200)