From cd0750e0457f26f8165be301ad628e1830bd1e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 25 Apr 2016 15:46:15 +0200 Subject: Prevent private project name and namespace from leaking in the new MR view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #15591. Signed-off-by: Rémy Coutable --- app/services/merge_requests/build_service.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app/services') diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index fa34753c4fd..3544752d47a 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -7,6 +7,9 @@ module MergeRequests merge_request.can_be_created = false merge_request.compare_commits = [] merge_request.source_project = project unless merge_request.source_project + + merge_request.target_project = nil unless can?(current_user, :read_project, merge_request.target_project) + merge_request.target_project ||= (project.forked_from_project || project) merge_request.target_branch ||= merge_request.target_project.default_branch -- cgit v1.2.1 From 247ae960552acc8cd3be299dbb10ed61d8dafe75 Mon Sep 17 00:00:00 2001 From: Long Nguyen Date: Tue, 26 Apr 2016 23:20:19 +0700 Subject: Allow to assign labels and milestone to target project when moving issue --- app/services/issues/move_service.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'app/services') diff --git a/app/services/issues/move_service.rb b/app/services/issues/move_service.rb index 82e7090f1ea..8d41ea5df55 100644 --- a/app/services/issues/move_service.rb +++ b/app/services/issues/move_service.rb @@ -41,7 +41,8 @@ module Issues private def create_new_issue - new_params = { id: nil, iid: nil, label_ids: [], milestone: nil, + new_params = { id: nil, iid: nil, label_ids: cloneable_label_ids, + milestone: cloneable_milestone_id, project: @new_project, author: @old_issue.author, description: rewrite_content(@old_issue.description) } @@ -49,6 +50,14 @@ module Issues CreateService.new(@new_project, @current_user, new_params).execute end + def cloneable_label_ids + @new_project.labels.where(title: @old_issue.labels.pluck(:title)).pluck(:id) + end + + def cloneable_milestone_id + @new_project.milestones.find_by(title: @old_issue.milestone.try(:title)) + end + def rewrite_notes @old_issue.notes.find_each do |note| new_note = note.dup -- cgit v1.2.1 From be67a4843cc37790402404650cb96a6f02552b54 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 26 Apr 2016 12:55:38 -0400 Subject: Prevent privilege escalation via notes API Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/15577 --- app/services/notes/create_service.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'app/services') diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index 2bb312bb252..01586994813 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -5,6 +5,8 @@ module Notes note.author = current_user note.system = false + return unless valid_project?(note) + if note.save # Finish the harder work in the background NewNoteWorker.perform_in(2.seconds, note.id, params) @@ -13,5 +15,14 @@ module Notes note end + + private + + def valid_project?(note) + return false unless project + return true if note.for_commit? + + note.noteable.try(:project) == project + end end end -- cgit v1.2.1 From f7844a11be6a5f6aa7011bd96f59bf218c4788ea Mon Sep 17 00:00:00 2001 From: Long Nguyen Date: Thu, 28 Apr 2016 15:52:23 +0700 Subject: Code refactor and fix broken spec --- app/services/issues/move_service.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'app/services') diff --git a/app/services/issues/move_service.rb b/app/services/issues/move_service.rb index 8d41ea5df55..fe5df8f18cb 100644 --- a/app/services/issues/move_service.rb +++ b/app/services/issues/move_service.rb @@ -42,7 +42,7 @@ module Issues def create_new_issue new_params = { id: nil, iid: nil, label_ids: cloneable_label_ids, - milestone: cloneable_milestone_id, + milestone_id: cloneable_milestone_id, project: @new_project, author: @old_issue.author, description: rewrite_content(@old_issue.description) } @@ -51,11 +51,13 @@ module Issues end def cloneable_label_ids - @new_project.labels.where(title: @old_issue.labels.pluck(:title)).pluck(:id) + @new_project.labels + .where(title: @old_issue.labels.pluck(:title)).pluck(:id) end def cloneable_milestone_id - @new_project.milestones.find_by(title: @old_issue.milestone.try(:title)) + @new_project.milestones + .find_by(title: @old_issue.milestone.try(:title)).try(:id) end def rewrite_notes -- cgit v1.2.1 From 3811eb0ba1e8c0f318060696853b1cab7f99dfa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 26 Apr 2016 12:54:49 +0200 Subject: Fix error when trying to create a wiki page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #15527. Signed-off-by: Rémy Coutable --- app/services/wiki_pages/create_service.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app/services') diff --git a/app/services/wiki_pages/create_service.rb b/app/services/wiki_pages/create_service.rb index 988c663b9d0..24a817c06c9 100644 --- a/app/services/wiki_pages/create_service.rb +++ b/app/services/wiki_pages/create_service.rb @@ -1,7 +1,8 @@ module WikiPages class CreateService < WikiPages::BaseService def execute - page = WikiPage.new(@project.wiki) + project_wiki = ProjectWiki.new(@project, current_user) + page = WikiPage.new(project_wiki) if page.create(@params) execute_hooks(page, 'create') -- cgit v1.2.1 From 44f89eafc08a7967544429a3f930354a5f9bbbaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 15 Apr 2016 12:15:52 +0200 Subject: Use Rugged's TagCollection#create instead of gitlab-shell's Repository#add_tag for better performance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- app/services/create_tag_service.rb | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'app/services') diff --git a/app/services/create_tag_service.rb b/app/services/create_tag_service.rb index 55985380d31..775f9db2a46 100644 --- a/app/services/create_tag_service.rb +++ b/app/services/create_tag_service.rb @@ -8,32 +8,28 @@ class CreateTagService < BaseService end repository = project.repository - existing_tag = repository.find_tag(tag_name) - if existing_tag - return error('Tag already exists') - end - message.strip! if message + begin + new_tag = repository.add_tag(current_user, tag_name, ref, message) + rescue Rugged::TagError + return error("Tag #{tag_name} already exists") + rescue Rugged::ReferenceError + return error("Target #{ref} is invalid") + end - repository.add_tag(tag_name, ref, message) - new_tag = repository.find_tag(tag_name) - - if new_tag - push_data = create_push_data(project, current_user, new_tag) - EventCreateService.new.push(project, current_user, push_data) - project.execute_hooks(push_data.dup, :tag_push_hooks) - project.execute_services(push_data.dup, :tag_push_hooks) - CreateCommitBuildsService.new.execute(project, current_user, push_data) + push_data = create_push_data(project, current_user, new_tag) - if release_description - CreateReleaseService.new(@project, @current_user). - execute(tag_name, release_description) - end + EventCreateService.new.push(project, current_user, push_data) + project.execute_hooks(push_data.dup, :tag_push_hooks) + project.execute_services(push_data.dup, :tag_push_hooks) + CreateCommitBuildsService.new.execute(project, current_user, push_data) - success(new_tag) - else - error('Invalid reference name') + if release_description + CreateReleaseService.new(@project, @current_user). + execute(tag_name, release_description) end + + success(new_tag) end def success(branch) -- cgit v1.2.1 From 209f2f1e6fd861dd7bb6a73389400b4bb266d26d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 25 Apr 2016 16:31:45 +0200 Subject: Use a similar approach to branch creation for tag creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- app/services/create_branch_service.rb | 5 ---- app/services/create_tag_service.rb | 46 ++++++++++++----------------------- 2 files changed, 15 insertions(+), 36 deletions(-) (limited to 'app/services') diff --git a/app/services/create_branch_service.rb b/app/services/create_branch_service.rb index 707c2f7ff85..9f4481a8153 100644 --- a/app/services/create_branch_service.rb +++ b/app/services/create_branch_service.rb @@ -43,9 +43,4 @@ class CreateBranchService < BaseService out[:branch] = branch out end - - def build_push_data(project, user, branch) - Gitlab::PushDataBuilder. - build(project, user, Gitlab::Git::BLANK_SHA, branch.target, "#{Gitlab::Git::BRANCH_REF_PREFIX}#{branch.name}", []) - end end diff --git a/app/services/create_tag_service.rb b/app/services/create_tag_service.rb index 775f9db2a46..91ed0e354d0 100644 --- a/app/services/create_tag_service.rb +++ b/app/services/create_tag_service.rb @@ -1,46 +1,30 @@ require_relative 'base_service' class CreateTagService < BaseService - def execute(tag_name, ref, message, release_description = nil) + def execute(tag_name, target, message, release_description = nil) valid_tag = Gitlab::GitRefValidator.validate(tag_name) - if valid_tag == false - return error('Tag name invalid') - end + return error('Tag name invalid') unless valid_tag repository = project.repository message.strip! if message + + new_tag = nil begin - new_tag = repository.add_tag(current_user, tag_name, ref, message) + new_tag = repository.add_tag(current_user, tag_name, target, message) rescue Rugged::TagError return error("Tag #{tag_name} already exists") - rescue Rugged::ReferenceError - return error("Target #{ref} is invalid") + rescue GitHooksService::PreReceiveError + return error('Tag creation was rejected by Git hook') end - push_data = create_push_data(project, current_user, new_tag) - - EventCreateService.new.push(project, current_user, push_data) - project.execute_hooks(push_data.dup, :tag_push_hooks) - project.execute_services(push_data.dup, :tag_push_hooks) - CreateCommitBuildsService.new.execute(project, current_user, push_data) - - if release_description - CreateReleaseService.new(@project, @current_user). - execute(tag_name, release_description) + if new_tag + if release_description + CreateReleaseService.new(@project, @current_user). + execute(tag_name, release_description) + end + success.merge(tag: new_tag) + else + error("Target #{target} is invalid") end - - success(new_tag) - end - - def success(branch) - out = super() - out[:tag] = branch - out - end - - def create_push_data(project, user, tag) - commits = [project.commit(tag.target)].compact - Gitlab::PushDataBuilder. - build(project, user, Gitlab::Git::BLANK_SHA, tag.target, "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}", commits, tag.message) end end -- cgit v1.2.1 From 525e05b6536123a3117b5ff53fd46a96382d5f9d Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 28 Apr 2016 16:48:37 -0700 Subject: Expire repository exists? and has_visible_content? caches after a push if necessary Closes #17012 --- app/services/git_push_service.rb | 1 + app/services/git_tag_push_service.rb | 1 + 2 files changed, 2 insertions(+) (limited to 'app/services') diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index b7af80055bf..66136b62617 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -17,6 +17,7 @@ class GitPushService < BaseService # 6. Checks if the project's main language has changed # def execute + @project.repository.after_create if @project.empty_repo? @project.repository.after_push_commit(branch_name, params[:newrev]) if push_remove_branch? diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb index 64271d8bc5c..7410442609d 100644 --- a/app/services/git_tag_push_service.rb +++ b/app/services/git_tag_push_service.rb @@ -2,6 +2,7 @@ class GitTagPushService < BaseService attr_accessor :push_data def execute + project.repository.after_create if project.empty_repo? project.repository.before_push_tag @push_data = build_push_data -- cgit v1.2.1 From 91f693c0c4f1ebb62d78e6c82b833f8a19c4dc62 Mon Sep 17 00:00:00 2001 From: Long Nguyen Date: Thu, 5 May 2016 13:59:09 +0700 Subject: Update changelog, improve specs --- app/services/issues/move_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/services') diff --git a/app/services/issues/move_service.rb b/app/services/issues/move_service.rb index fe5df8f18cb..e61628086f0 100644 --- a/app/services/issues/move_service.rb +++ b/app/services/issues/move_service.rb @@ -46,7 +46,7 @@ module Issues project: @new_project, author: @old_issue.author, description: rewrite_content(@old_issue.description) } - new_params = @old_issue.serializable_hash.merge(new_params) + new_params = @old_issue.serializable_hash.symbolize_keys.merge(new_params) CreateService.new(@new_project, @current_user, new_params).execute end -- cgit v1.2.1 From e76f339dcd83799a63d206007750077b7af753f4 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 28 Apr 2016 11:36:37 +0100 Subject: Auto-set title for branches created from issues If a branch starts with an issue's IID, followed by a hyphen, the description will be updated to say that is closes the issue. This also updates the title of the merge request to 'Resolves "$issue-title"', as long as: - There is more than one commit in the merge request (if there is only one commit, the commit's title will be used as before) - The issue's IID is valid for the project --- app/services/merge_requests/build_service.rb | 36 +++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'app/services') diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index 3544752d47a..4add1d66ea5 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -41,21 +41,45 @@ module MergeRequests merge_request.can_be_created = false end + set_title_and_description(merge_request) + end + + private + + # When your branch name starts with an iid followed by a dash this pattern will be + # interpreted as the user wants to close that issue on this project. + # + # For example: + # - Issue 112 exists, title: Emoji don't show up in commit title + # - Source branch is: 112-fix-mep-mep + # + # Will lead to: + # - Appending `Closes #112` to the description + # - Setting the title as 'Resolves "Emoji don't show up in commit title"' if there is + # more than one commit in the MR + # + def set_title_and_description(merge_request) + if match = merge_request.source_branch.match(/\A(\d+)-/) + iid = match[1] + end + commits = merge_request.compare_commits if commits && commits.count == 1 commit = commits.first merge_request.title = commit.title merge_request.description ||= commit.description.try(:strip) + elsif iid && (issue = merge_request.target_project.get_issue(iid)) + case issue + when Issue + merge_request.title = "Resolve \"#{issue.title}\"" + when ExternalIssue + merge_request.title = "Resolve #{issue.title}" + end else merge_request.title = merge_request.source_branch.titleize.humanize end - # When your branch name starts with an iid followed by a dash this pattern will - # be interpreted as the use wants to close that issue on this project - # Pattern example: 112-fix-mep-mep - # Will lead to appending `Closes #112` to the description - if match = merge_request.source_branch.match(/\A(\d+)-/) - iid = match[1] + if iid closes_issue = "Closes ##{iid}" if merge_request.description.present? -- cgit v1.2.1 From 09209725cee58b3d9645b8cf58ec955b566f5b5b Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 28 Apr 2016 12:12:03 +0100 Subject: Don't auto-set MR title for confidential issues --- app/services/merge_requests/build_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/services') diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index 4add1d66ea5..cd4230aa5e4 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -68,7 +68,7 @@ module MergeRequests commit = commits.first merge_request.title = commit.title merge_request.description ||= commit.description.try(:strip) - elsif iid && (issue = merge_request.target_project.get_issue(iid)) + elsif iid && (issue = merge_request.target_project.get_issue(iid)) && !issue.try(:confidential?) case issue when Issue merge_request.title = "Resolve \"#{issue.title}\"" -- cgit v1.2.1 From a65de9c2c1b8ea2d7dca3132ff0d72775f04bb78 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 1 May 2016 00:38:53 -0700 Subject: Reduce delay in destroying a project from 1-minute to immediately Run ProjectDestroyWorker after pending_delete attribute has been committed to DB --- app/services/projects/destroy_service.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'app/services') diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index df5054f08d7..19aab999e00 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -7,9 +7,7 @@ module Projects DELETED_FLAG = '+deleted' def pending_delete! - project.update_attribute(:pending_delete, true) - - ProjectDestroyWorker.perform_in(1.minute, project.id, current_user.id, params) + project.schedule_delete!(current_user.id, params) end def execute -- cgit v1.2.1 From daca2144c80546169fb35fcf76b1f3d052b643cc Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 9 May 2016 20:47:06 +0300 Subject: Make code more clear in what is done --- app/services/jwt/docker_authentication_service.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'app/services') diff --git a/app/services/jwt/docker_authentication_service.rb b/app/services/jwt/docker_authentication_service.rb index ce28085e5d6..fb0c41a12f7 100644 --- a/app/services/jwt/docker_authentication_service.rb +++ b/app/services/jwt/docker_authentication_service.rb @@ -5,12 +5,12 @@ module Jwt return error('forbidden', 403) unless current_user end - { token: token.encoded } + { token: authorized_token.encoded } end private - def token + def authorized_token token = ::Jwt::RSAToken.new(registry.key) token.issuer = registry.issuer token.audience = params[:service] @@ -37,22 +37,22 @@ module Jwt end def process_repository_access(type, name, actions) - current_project = Project.find_with_namespace(name) - return unless current_project + requested_project = Project.find_with_namespace(name) + return unless requested_project actions = actions.select do |action| - can_access?(current_project, action) + can_access?(requested_project, action) end { type: type, name: name, actions: actions } if actions end - def can_access?(current_project, action) - case action + def can_access?(requested_project, requested_action) + case requested_action when 'pull' - current_project == project || can?(current_user, :download_code, current_project) + requested_project.public? || requested_project == project || can?(current_user, :download_code, requested_project) when 'push' - current_project == project || can?(current_user, :push_code, current_project) + requested_project == project || can?(current_user, :push_code, requested_project) else false end -- cgit v1.2.1 From b180d79cdca2ce0f6aa7425baf47db5b9c1ec2e3 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 9 May 2016 22:04:42 +0300 Subject: Rename DockerAuthenticationService to ContainerRegistryAuthenticationService --- .../container_registry_authentication_service.rb | 69 ++++++++++++++++++++++ app/services/jwt/docker_authentication_service.rb | 65 -------------------- 2 files changed, 69 insertions(+), 65 deletions(-) create mode 100644 app/services/jwt/container_registry_authentication_service.rb delete mode 100644 app/services/jwt/docker_authentication_service.rb (limited to 'app/services') diff --git a/app/services/jwt/container_registry_authentication_service.rb b/app/services/jwt/container_registry_authentication_service.rb new file mode 100644 index 00000000000..b9fcd380475 --- /dev/null +++ b/app/services/jwt/container_registry_authentication_service.rb @@ -0,0 +1,69 @@ +module Jwt + class ContainerRegistryAuthenticationService < BaseService + def execute + if params[:offline_token] + return error('forbidden', 403) unless current_user + end + + return error('forbidden', 401) if scopes.empty? + + { token: authorized_token(scopes).encoded } + end + + private + + def authorized_token(access) + token = ::Jwt::RSAToken.new(registry.key) + token.issuer = registry.issuer + token.audience = params[:service] + token.subject = current_user.try(:username) + token[:access] = access + token + end + + def scopes + return unless params[:scope] + + @scopes ||= begin + scope = process_scope(params[:scope]) + [scope].compact + end + end + + def process_scope(scope) + type, name, actions = scope.split(':', 3) + actions = actions.split(',') + + case type + when 'repository' + process_repository_access(type, name, actions) + end + end + + def process_repository_access(type, name, actions) + requested_project = Project.find_with_namespace(name) + return unless requested_project + + actions = actions.select do |action| + can_access?(requested_project, action) + end + + { type: type, name: name, actions: actions } if actions.present? + end + + def can_access?(requested_project, requested_action) + case requested_action + when 'pull' + requested_project.public? || requested_project == project || can?(current_user, :read_container_registry, requested_project) + when 'push' + requested_project == project || can?(current_user, :create_container_registry, requested_project) + else + false + end + end + + def registry + Gitlab.config.registry + end + end +end diff --git a/app/services/jwt/docker_authentication_service.rb b/app/services/jwt/docker_authentication_service.rb deleted file mode 100644 index fb0c41a12f7..00000000000 --- a/app/services/jwt/docker_authentication_service.rb +++ /dev/null @@ -1,65 +0,0 @@ -module Jwt - class DockerAuthenticationService < BaseService - def execute - if params[:offline_token] - return error('forbidden', 403) unless current_user - end - - { token: authorized_token.encoded } - end - - private - - def authorized_token - token = ::Jwt::RSAToken.new(registry.key) - token.issuer = registry.issuer - token.audience = params[:service] - token.subject = current_user.try(:username) - token[:access] = access - token - end - - def access - return unless params[:scope] - - scope = process_scope(params[:scope]) - [scope].compact - end - - def process_scope(scope) - type, name, actions = scope.split(':', 3) - actions = actions.split(',') - - case type - when 'repository' - process_repository_access(type, name, actions) - end - end - - def process_repository_access(type, name, actions) - requested_project = Project.find_with_namespace(name) - return unless requested_project - - actions = actions.select do |action| - can_access?(requested_project, action) - end - - { type: type, name: name, actions: actions } if actions - end - - def can_access?(requested_project, requested_action) - case requested_action - when 'pull' - requested_project.public? || requested_project == project || can?(current_user, :download_code, requested_project) - when 'push' - requested_project == project || can?(current_user, :push_code, requested_project) - else - false - end - end - - def registry - Gitlab.config.registry - end - end -end -- cgit v1.2.1