diff options
author | Alfredo Sumaran <alfredo@gitlab.com> | 2016-03-22 11:13:27 -0500 |
---|---|---|
committer | Alfredo Sumaran <alfredo@gitlab.com> | 2016-03-22 11:13:27 -0500 |
commit | a42b2c388df5154eecefd8eb7d8a68373e794d6e (patch) | |
tree | 7cfcbca6f78d66fb05d56586f322067dcb4d9c92 /app/services | |
parent | 647f28bd1d92eabe239a7f0f4a65eb100c0cda73 (diff) | |
parent | 18c049886e0f9ad2d094f02483aea272d0e029fb (diff) | |
download | gitlab-ce-a42b2c388df5154eecefd8eb7d8a68373e794d6e.tar.gz |
Merge branch 'master' into issue_7959
Diffstat (limited to 'app/services')
24 files changed, 272 insertions, 84 deletions
diff --git a/app/services/base_service.rb b/app/services/base_service.rb index 8563633816c..0d55ba5a981 100644 --- a/app/services/base_service.rb +++ b/app/services/base_service.rb @@ -43,12 +43,9 @@ class BaseService def deny_visibility_level(model, denied_visibility_level = nil) denied_visibility_level ||= model.visibility_level - level_name = Gitlab::VisibilityLevel.level_name(denied_visibility_level) + level_name = Gitlab::VisibilityLevel.level_name(denied_visibility_level).downcase - model.errors.add( - :visibility_level, - "#{level_name} visibility has been restricted by your GitLab administrator" - ) + model.errors.add(:visibility_level, "#{level_name} has been restricted by your GitLab administrator") end private diff --git a/app/services/ci/create_builds_service.rb b/app/services/ci/create_builds_service.rb index 002f7ba1278..2cd51a7610f 100644 --- a/app/services/ci/create_builds_service.rb +++ b/app/services/ci/create_builds_service.rb @@ -1,7 +1,7 @@ module Ci class CreateBuildsService def execute(commit, stage, ref, tag, user, trigger_request, status) - builds_attrs = commit.config_processor.builds_for_stage_and_ref(stage, ref, tag) + builds_attrs = commit.config_processor.builds_for_stage_and_ref(stage, ref, tag, trigger_request) # check when to create next build builds_attrs = builds_attrs.select do |build_attrs| diff --git a/app/services/commits/revert_service.rb b/app/services/commits/revert_service.rb index 9cb918d7a2e..a3c950ede1f 100644 --- a/app/services/commits/revert_service.rb +++ b/app/services/commits/revert_service.rb @@ -9,7 +9,8 @@ module Commits @commit = params[:commit] @create_merge_request = params[:create_merge_request].present? - validate and commit + check_push_permissions unless @create_merge_request + commit rescue Repository::CommitError, Gitlab::Git::Repository::InvalidBlobName, GitHooksService::PreReceiveError, ValidationError, ReversionError => ex error(ex.message) @@ -45,11 +46,11 @@ module Commits end end - def validate + def check_push_permissions allowed = ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(@target_branch) unless allowed - raise_error('You are not allowed to push into this branch') + raise ValidationError.new('You are not allowed to push into this branch') end true diff --git a/app/services/create_snippet_service.rb b/app/services/create_snippet_service.rb index 101a3df5eee..9884cb96661 100644 --- a/app/services/create_snippet_service.rb +++ b/app/services/create_snippet_service.rb @@ -6,8 +6,7 @@ class CreateSnippetService < BaseService snippet = project.snippets.build(params) end - unless Gitlab::VisibilityLevel.allowed_for?(current_user, - params[:visibility_level]) + unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) deny_visibility_level(snippet) return snippet end diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index d840ab5e340..c007d648dd6 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -17,7 +17,7 @@ class GitPushService < BaseService # 6. Checks if the project's main language has changed # def execute - @project.repository.after_push_commit(branch_name) + @project.repository.after_push_commit(branch_name, params[:newrev]) if push_remove_branch? @project.repository.after_remove_branch @@ -120,7 +120,7 @@ class GitPushService < BaseService closed_issues = commit.closes_issues(current_user) closed_issues.each do |issue| if can?(current_user, :update_issue, issue) - Issues::CloseService.new(project, authors[commit], {}).execute(issue, commit) + Issues::CloseService.new(project, authors[commit], {}).execute(issue, commit: commit) end end end diff --git a/app/services/groups/base_service.rb b/app/services/groups/base_service.rb new file mode 100644 index 00000000000..a8fa098246a --- /dev/null +++ b/app/services/groups/base_service.rb @@ -0,0 +1,9 @@ +module Groups + class BaseService < ::BaseService + attr_accessor :group, :current_user, :params + + def initialize(group, user, params = {}) + @group, @current_user, @params = group, user, params.dup + end + end +end diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb new file mode 100644 index 00000000000..2bccd584dde --- /dev/null +++ b/app/services/groups/create_service.rb @@ -0,0 +1,21 @@ +module Groups + class CreateService < Groups::BaseService + def initialize(user, params = {}) + @current_user, @params = user, params.dup + end + + def execute + @group = Group.new(params) + + unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) + deny_visibility_level(@group) + return @group + end + + @group.name ||= @group.path.dup + @group.save + @group.add_owner(current_user) + @group + end + end +end diff --git a/app/services/groups/update_service.rb b/app/services/groups/update_service.rb new file mode 100644 index 00000000000..99ad12b1003 --- /dev/null +++ b/app/services/groups/update_service.rb @@ -0,0 +1,20 @@ +module Groups + class UpdateService < Groups::BaseService + def execute + # check that user is allowed to set specified visibility_level + new_visibility = params[:visibility_level] + if new_visibility && new_visibility.to_i != group.visibility_level + unless can?(current_user, :change_visibility_level, group) && + Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility) + + deny_visibility_level(group, new_visibility) + return group + end + end + + group.assign_attributes(params) + + group.save + end + end +end diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb index 78254b49af3..859c934ea3b 100644 --- a/app/services/issues/close_service.rb +++ b/app/services/issues/close_service.rb @@ -1,6 +1,6 @@ module Issues class CloseService < Issues::BaseService - def execute(issue, commit = nil) + def execute(issue, commit: nil, notifications: true, system_note: true) if project.jira_tracker? && project.jira_service.active project.jira_service.execute(commit, issue) todo_service.close_issue(issue, current_user) @@ -9,8 +9,8 @@ module Issues if project.default_issues_tracker? && issue.close event_service.close_issue(issue, current_user) - create_note(issue, commit) - notification_service.close_issue(issue, current_user) + create_note(issue, commit) if system_note + notification_service.close_issue(issue, current_user) if notifications todo_service.close_issue(issue, current_user) execute_hooks(issue, 'close') end diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb index 10787e8873c..e63e1af8766 100644 --- a/app/services/issues/create_service.rb +++ b/app/services/issues/create_service.rb @@ -4,7 +4,7 @@ module Issues filter_params label_params = params[:label_ids] issue = project.issues.new(params.except(:label_ids)) - issue.author = current_user + issue.author = params[:author] || current_user if issue.save issue.update_attributes(label_ids: label_params) diff --git a/app/services/issues/move_service.rb b/app/services/issues/move_service.rb new file mode 100644 index 00000000000..3cfbafe1576 --- /dev/null +++ b/app/services/issues/move_service.rb @@ -0,0 +1,94 @@ +module Issues + class MoveService < Issues::BaseService + class MoveError < StandardError; end + + def execute(issue, new_project) + @old_issue = issue + @old_project = @project + @new_project = new_project + + unless issue.can_move?(current_user, new_project) + raise MoveError, 'Cannot move issue due to insufficient permissions!' + end + + if @project == new_project + raise MoveError, 'Cannot move issue to project it originates from!' + end + + # Using transaction because of a high resources footprint + # on rewriting notes (unfolding references) + # + ActiveRecord::Base.transaction do + # New issue tasks + # + @new_issue = create_new_issue + + rewrite_notes + add_note_moved_from + + # Old issue tasks + # + add_note_moved_to + close_issue + mark_as_moved + end + + notify_participants + + @new_issue + end + + private + + def create_new_issue + new_params = { id: nil, iid: nil, label_ids: [], milestone: nil, + project: @new_project, author: @old_issue.author, + description: unfold_references(@old_issue.description) } + + new_params = @old_issue.serializable_hash.merge(new_params) + CreateService.new(@new_project, @current_user, new_params).execute + end + + def rewrite_notes + @old_issue.notes.find_each do |note| + new_note = note.dup + new_params = { project: @new_project, noteable: @new_issue, + note: unfold_references(new_note.note), + created_at: note.created_at } + + new_note.update(new_params) + end + end + + def close_issue + close_service = CloseService.new(@old_project, @current_user) + close_service.execute(@old_issue, notifications: false, system_note: false) + end + + def add_note_moved_from + SystemNoteService.noteable_moved(@new_issue, @new_project, + @old_issue, @current_user, + direction: :from) + end + + def add_note_moved_to + SystemNoteService.noteable_moved(@old_issue, @old_project, + @new_issue, @current_user, + direction: :to) + end + + def unfold_references(content) + rewriter = Gitlab::Gfm::ReferenceRewriter.new(content, @old_project, + @current_user) + rewriter.rewrite(@new_project) + end + + def notify_participants + notification_service.issue_moved(@old_issue, @new_issue, @current_user) + end + + def mark_as_moved + @old_issue.update(moved_to: @new_issue) + end + end +end diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb index 7b306a8a531..ac5b58db862 100644 --- a/app/services/merge_requests/base_service.rb +++ b/app/services/merge_requests/base_service.rb @@ -5,6 +5,19 @@ module MergeRequests SystemNoteService.change_status(merge_request, merge_request.target_project, current_user, merge_request.state, nil) end + def create_title_change_note(issuable, old_title) + removed_wip = old_title =~ MergeRequest::WIP_REGEX && !issuable.work_in_progress? + added_wip = old_title !~ MergeRequest::WIP_REGEX && issuable.work_in_progress? + + if removed_wip + SystemNoteService.remove_merge_request_wip(issuable, issuable.project, current_user) + elsif added_wip + SystemNoteService.add_merge_request_wip(issuable, issuable.project, current_user) + else + super + end + end + def hook_data(merge_request, action) hook_data = merge_request.to_hook_data(current_user) merge_request_url = Gitlab::UrlBuilder.new(:merge_request).build(merge_request.id) diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index fa34753c4fd..6e9152e444e 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -51,7 +51,7 @@ module MergeRequests # 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+)-/) + if match = merge_request.source_branch.match(/-(\d+)\z/) iid = match[1] closes_issue = "Closes ##{iid}" diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb index ebb67c7db65..064910f81f7 100644 --- a/app/services/merge_requests/post_merge_service.rb +++ b/app/services/merge_requests/post_merge_service.rb @@ -22,7 +22,7 @@ module MergeRequests closed_issues = merge_request.closes_issues(current_user) closed_issues.each do |issue| if can?(current_user, :update_issue, issue) - Issues::CloseService.new(project, current_user, {}).execute(issue, merge_request) + Issues::CloseService.new(project, current_user, {}).execute(issue, commit: merge_request) end end end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 19a6779dea9..3bdf00a8291 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -236,6 +236,16 @@ class NotificationService end end + def issue_moved(issue, new_issue, current_user) + recipients = build_recipients(issue, issue.project, current_user) + + recipients.map do |recipient| + email = mailer.issue_moved_email(recipient, issue, new_issue, current_user) + email.deliver_later + email + end + end + protected # Get project users with WATCH notification level diff --git a/app/services/projects/autocomplete_service.rb b/app/services/projects/autocomplete_service.rb index 7408e09ed1e..ba50305dbd5 100644 --- a/app/services/projects/autocomplete_service.rb +++ b/app/services/projects/autocomplete_service.rb @@ -1,11 +1,7 @@ module Projects class AutocompleteService < BaseService - def initialize(project) - @project = project - end - def issues - @project.issues.opened.select([:iid, :title]) + @project.issues.visible_to_user(current_user).opened.select([:iid, :title]) end def merge_requests diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index a6820183bee..501e58c1407 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -9,10 +9,8 @@ module Projects @project = Project.new(params) - # Make sure that the user is allowed to use the specified visibility - # level - unless Gitlab::VisibilityLevel.allowed_for?(current_user, - params[:visibility_level]) + # Make sure that the user is allowed to use the specified visibility level + unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) deny_visibility_level(@project) return @project end @@ -55,9 +53,7 @@ module Projects @project.save if @project.persisted? && !@project.import? - unless @project.create_repository - raise 'Failed to create repository' - end + raise 'Failed to create repository' unless @project.create_repository end end diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb index bccd67d3dbf..a0973c5d260 100644 --- a/app/services/projects/housekeeping_service.rb +++ b/app/services/projects/housekeeping_service.rb @@ -24,7 +24,7 @@ module Projects def execute raise LeaseTaken if !try_obtain_lease - GitlabShellWorker.perform_async(:gc, @project.path_with_namespace) + GitlabShellOneShotWorker.perform_async(:gc, @project.path_with_namespace) ensure @project.update_column(:pushes_since_gc, 0) end diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index 895e089bea3..941df08995c 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -3,16 +3,13 @@ module Projects def execute # check that user is allowed to set specified visibility_level new_visibility = params[:visibility_level] - if new_visibility - if new_visibility.to_i != project.visibility_level - unless can?(current_user, :change_visibility_level, project) && - Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility) - deny_visibility_level(project, new_visibility) - return project - end + if new_visibility && new_visibility.to_i != project.visibility_level + unless can?(current_user, :change_visibility_level, project) && + Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility) + + deny_visibility_level(project, new_visibility) + return project end - - return false unless visibility_level_allowed?(new_visibility) end new_branch = params[:default_branch] @@ -27,19 +24,5 @@ module Projects end end end - - private - - def visibility_level_allowed?(level) - return true if project.visibility_level_allowed?(level) - - level_name = Gitlab::VisibilityLevel.level_name(level) - project.errors.add( - :visibility_level, - "#{level_name} could not be set as visibility level of this project - parent project settings are more restrictive" - ) - - false - end end end diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb index e1e94c5cc38..aa9837038a6 100644 --- a/app/services/search/global_service.rb +++ b/app/services/search/global_service.rb @@ -11,7 +11,7 @@ module Search projects = ProjectsFinder.new.execute(current_user) projects = projects.in_namespace(group.id) if group - Gitlab::SearchResults.new(projects, params[:search]) + Gitlab::SearchResults.new(current_user, projects, params[:search]) end end end diff --git a/app/services/search/project_service.rb b/app/services/search/project_service.rb index c08881dce4b..4b500914cfb 100644 --- a/app/services/search/project_service.rb +++ b/app/services/search/project_service.rb @@ -7,7 +7,8 @@ module Search end def execute - Gitlab::ProjectSearchResults.new(project, + Gitlab::ProjectSearchResults.new(current_user, + project, params[:search], params[:repository_ref]) end diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index f09b77c4a57..e022a046c48 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -144,6 +144,18 @@ class SystemNoteService create_note(noteable: noteable, project: project, author: author, note: body) end + def self.remove_merge_request_wip(noteable, project, author) + body = 'Unmarked this merge request as a Work In Progress' + + create_note(noteable: noteable, project: project, author: author, note: body) + end + + def self.add_merge_request_wip(noteable, project, author) + body = 'Marked this merge request as a **Work In Progress**' + + create_note(noteable: noteable, project: project, author: author, note: body) + end + # Called when the title of a Noteable is changed # # noteable - Noteable object that responds to `title` @@ -210,7 +222,7 @@ class SystemNoteService # Called when a branch is created from the 'new branch' button on a issue # Example note text: # - # "Started branch `201-issue-branch-button`" + # "Started branch `issue-branch-button-201`" def self.new_issue_branch(issue, project, author, branch) h = Gitlab::Application.routes.url_helpers link = h.namespace_project_compare_url(project.namespace, project, from: project.default_branch, to: branch) @@ -399,4 +411,26 @@ class SystemNoteService body = "Marked the task **#{new_task.source}** as #{status_label}" create_note(noteable: noteable, project: project, author: author, note: body) end + + # Called when noteable has been moved to another project + # + # direction - symbol, :to or :from + # noteable - Noteable object + # noteable_ref - Referenced noteable + # author - User performing the move + # + # Example Note text: + # + # "Moved to some_namespace/project_new#11" + # + # Returns the created Note object + def self.noteable_moved(noteable, project, noteable_ref, author, direction:) + unless [:to, :from].include?(direction) + raise ArgumentError, "Invalid direction `#{direction}`" + end + + cross_reference = noteable_ref.to_reference(project) + body = "Moved #{direction} #{cross_reference}" + create_note(noteable: noteable, project: project, author: author, note: body) + end end diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb index 4392e2d17fe..f2662922e90 100644 --- a/app/services/todo_service.rb +++ b/app/services/todo_service.rb @@ -103,24 +103,16 @@ class TodoService # * mark all pending todos related to the target for the current user as done # def mark_pending_todos_as_done(target, user) - pending_todos(user, target.project, target).update_all(state: :done) + attributes = attributes_for_target(target) + pending_todos(user, attributes).update_all(state: :done) end private - def create_todos(project, target, author, users, action, note = nil) + def create_todos(users, attributes) Array(users).each do |user| - next if pending_todos(user, project, target).exists? - - Todo.create( - project: project, - user_id: user.id, - author_id: author.id, - target_id: target.id, - target_type: target.class.name, - action: action, - note: note - ) + next if pending_todos(user, attributes).exists? + Todo.create(attributes.merge(user_id: user.id)) end end @@ -130,8 +122,8 @@ class TodoService end def handle_note(note, author) - # Skip system notes, notes on commit, and notes on project snippet - return if note.system? || ['Commit', 'Snippet'].include?(note.noteable_type) + # Skip system notes, and notes on project snippet + return if note.system? || note.for_project_snippet? project = note.project target = note.noteable @@ -142,13 +134,39 @@ class TodoService def create_assignment_todo(issuable, author) if issuable.assignee && issuable.assignee != author - create_todos(issuable.project, issuable, author, issuable.assignee, Todo::ASSIGNED) + attributes = attributes_for_todo(issuable.project, issuable, author, Todo::ASSIGNED) + create_todos(issuable.assignee, attributes) end end - def create_mention_todos(project, issuable, author, note = nil) - mentioned_users = filter_mentioned_users(project, note || issuable, author) - create_todos(project, issuable, author, mentioned_users, Todo::MENTIONED, note) + def create_mention_todos(project, target, author, note = nil) + mentioned_users = filter_mentioned_users(project, note || target, author) + attributes = attributes_for_todo(project, target, author, Todo::MENTIONED, note) + create_todos(mentioned_users, attributes) + end + + def attributes_for_target(target) + attributes = { + project_id: target.project.id, + target_id: target.id, + target_type: target.class.name, + commit_id: nil + } + + if target.is_a?(Commit) + attributes.merge!(target_id: nil, commit_id: target.id) + end + + attributes + end + + def attributes_for_todo(project, target, author, action, note = nil) + attributes_for_target(target).merge!( + project_id: project.id, + author_id: author.id, + action: action, + note: note + ) end def filter_mentioned_users(project, target, author) @@ -160,11 +178,8 @@ class TodoService mentioned_users.uniq end - def pending_todos(user, project, target) - user.todos.pending.where( - project_id: project.id, - target_id: target.id, - target_type: target.class.name - ) + def pending_todos(user, criteria = {}) + valid_keys = [:project_id, :target_id, :target_type, :commit_id] + user.todos.pending.where(criteria.slice(*valid_keys)) end end diff --git a/app/services/update_snippet_service.rb b/app/services/update_snippet_service.rb index e9328bb7323..93af8f21972 100644 --- a/app/services/update_snippet_service.rb +++ b/app/services/update_snippet_service.rb @@ -9,7 +9,6 @@ class UpdateSnippetService < BaseService def execute # check that user is allowed to set specified visibility_level new_visibility = params[:visibility_level] - if new_visibility && new_visibility.to_i != snippet.visibility_level unless Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility) deny_visibility_level(snippet, new_visibility) |