diff --git a/app/contexts/base_context.rb b/app/contexts/base_context.rb deleted file mode 100644 index 6accd9b..0000000 --- a/app/contexts/base_context.rb +++ /dev/null @@ -1,19 +0,0 @@ -class BaseContext - attr_accessor :project, :current_user, :params - - def initialize(project, user, params) - @project, @current_user, @params = project, user, params.dup - end - - def abilities - @abilities ||= begin - abilities = Six.new - abilities << Ability - abilities - end - end - - def can?(object, action, subject) - abilities.allowed?(object, action, subject) - end -end diff --git a/app/contexts/files/base_context.rb b/app/contexts/files/base_context.rb deleted file mode 100644 index 44f9826..0000000 --- a/app/contexts/files/base_context.rb +++ /dev/null @@ -1,31 +0,0 @@ -module Files - class BaseContext < ::BaseContext - attr_reader :ref, :path - - def initialize(project, user, params, ref, path = nil) - @project, @current_user, @params = project, user, params.dup - @ref = ref - @path = path - end - - private - - def error(message) - { - error: message, - status: :error - } - end - - def success - { - error: '', - status: :success - } - end - - def repository - project.repository - end - end -end diff --git a/app/contexts/files/create_context.rb b/app/contexts/files/create_context.rb deleted file mode 100644 index b3d62a0..0000000 --- a/app/contexts/files/create_context.rb +++ /dev/null @@ -1,46 +0,0 @@ -require_relative "base_context" - -module Files - class CreateContext < BaseContext - def execute - allowed = if project.protected_branch?(ref) - can?(current_user, :push_code_to_protected_branches, project) - else - can?(current_user, :push_code, project) - end - - unless allowed - return error("You are not allowed to create file in this branch") - end - - unless repository.branch_names.include?(ref) - return error("You can only create files if you are on top of a branch") - end - - file_name = File.basename(path) - file_path = path - - unless file_name =~ Gitlab::Regex.path_regex - return error("Your changes could not be committed, because file name contains not allowed characters") - end - - blob = repository.blob_at(ref, file_path) - - if blob - return error("Your changes could not be committed, because file with such name exists") - end - - new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, file_path) - created_successfully = new_file_action.commit!( - params[:content], - params[:commit_message] - ) - - if created_successfully - success - else - error("Your changes could not be committed, because the file has been changed") - end - end - end -end diff --git a/app/contexts/files/delete_context.rb b/app/contexts/files/delete_context.rb deleted file mode 100644 index 39ff7c2..0000000 --- a/app/contexts/files/delete_context.rb +++ /dev/null @@ -1,40 +0,0 @@ -require_relative "base_context" - -module Files - class DeleteContext < BaseContext - def execute - allowed = if project.protected_branch?(ref) - can?(current_user, :push_code_to_protected_branches, project) - else - can?(current_user, :push_code, project) - end - - unless allowed - return error("You are not allowed to push into this branch") - end - - unless repository.branch_names.include?(ref) - return error("You can only create files if you are on top of a branch") - end - - blob = repository.blob_at(ref, path) - - unless blob - return error("You can only edit text files") - end - - delete_file_action = Gitlab::Satellite::DeleteFileAction.new(current_user, project, ref, path) - - deleted_successfully = delete_file_action.commit!( - nil, - params[:commit_message] - ) - - if deleted_successfully - success - else - error("Your changes could not be committed, because the file has been changed") - end - end - end -end diff --git a/app/contexts/files/update_context.rb b/app/contexts/files/update_context.rb deleted file mode 100644 index 556027a..0000000 --- a/app/contexts/files/update_context.rb +++ /dev/null @@ -1,39 +0,0 @@ -require_relative "base_context" - -module Files - class UpdateContext < BaseContext - def execute - allowed = if project.protected_branch?(ref) - can?(current_user, :push_code_to_protected_branches, project) - else - can?(current_user, :push_code, project) - end - - unless allowed - return error("You are not allowed to push into this branch") - end - - unless repository.branch_names.include?(ref) - return error("You can only create files if you are on top of a branch") - end - - blob = repository.blob_at(ref, path) - - unless blob - return error("You can only edit text files") - end - - new_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path) - created_successfully = new_file_action.commit!( - params[:content], - params[:commit_message] - ) - - if created_successfully - success - else - error("Your changes could not be committed, because the file has been changed") - end - end - end -end diff --git a/app/contexts/issues/bulk_update_context.rb b/app/contexts/issues/bulk_update_context.rb deleted file mode 100644 index ab38a4f..0000000 --- a/app/contexts/issues/bulk_update_context.rb +++ /dev/null @@ -1,39 +0,0 @@ -module Issues - class BulkUpdateContext < BaseContext - def execute - update_data = params[:update] - - issues_ids = update_data[:issues_ids].split(",") - milestone_id = update_data[:milestone_id] - assignee_id = update_data[:assignee_id] - status = update_data[:status] - - new_state = nil - - if status.present? - if status == 'closed' - new_state = :close - else - new_state = :reopen - end - end - - opts = {} - opts[:milestone_id] = milestone_id if milestone_id.present? - opts[:assignee_id] = assignee_id if assignee_id.present? - - issues = Issue.where(id: issues_ids) - issues = issues.select { |issue| can?(current_user, :modify_issue, issue) } - - issues.each do |issue| - issue.update_attributes(opts) - issue.send new_state if new_state - end - - { - count: issues.count, - success: !issues.count.zero? - } - end - end -end diff --git a/app/contexts/notes/create_context.rb b/app/contexts/notes/create_context.rb deleted file mode 100644 index 36ea76f..0000000 --- a/app/contexts/notes/create_context.rb +++ /dev/null @@ -1,10 +0,0 @@ -module Notes - class CreateContext < BaseContext - def execute - note = project.notes.new(params[:note]) - note.author = current_user - note.save - note - end - end -end diff --git a/app/contexts/notes/load_context.rb b/app/contexts/notes/load_context.rb deleted file mode 100644 index 234e9ac..0000000 --- a/app/contexts/notes/load_context.rb +++ /dev/null @@ -1,20 +0,0 @@ -module Notes - class LoadContext < BaseContext - def execute - target_type = params[:target_type] - target_id = params[:target_id] - - - @notes = case target_type - when "commit" - project.notes.for_commit_id(target_id).not_inline.fresh - when "issue" - project.issues.find(target_id).notes.inc_author.fresh - when "merge_request" - project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh - when "snippet" - project.snippets.find(target_id).notes.fresh - end - end - end -end diff --git a/app/contexts/projects/create_context.rb b/app/contexts/projects/create_context.rb deleted file mode 100644 index 2acb9fb..0000000 --- a/app/contexts/projects/create_context.rb +++ /dev/null @@ -1,80 +0,0 @@ -module Projects - class CreateContext < BaseContext - def initialize(user, params) - @current_user, @params = user, params.dup - end - - def execute - # get namespace id - namespace_id = params.delete(:namespace_id) - - # check that user is allowed to set specified visibility_level - unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) - params.delete(:visibility_level) - end - - # Load default feature settings - default_features = Gitlab.config.gitlab.default_projects_features - - default_opts = { - issues_enabled: default_features.issues, - wiki_enabled: default_features.wiki, - wall_enabled: default_features.wall, - snippets_enabled: default_features.snippets, - merge_requests_enabled: default_features.merge_requests, - visibility_level: default_features.visibility_level - }.stringify_keys - - @project = Project.new(default_opts.merge(params)) - - # Parametrize path for project - # - # Ex. - # 'GitLab HQ'.parameterize => "gitlab-hq" - # - @project.path = @project.name.dup.parameterize unless @project.path.present? - - - if namespace_id - # Find matching namespace and check if it allowed - # for current user if namespace_id passed. - if allowed_namespace?(current_user, namespace_id) - @project.namespace_id = namespace_id - else - deny_namespace - return @project - end - else - # Set current user namespace if namespace_id is nil - @project.namespace_id = current_user.namespace_id - end - - @project.creator = current_user - - if @project.save - unless @project.group - @project.users_projects.create( - project_access: UsersProject::MASTER, - user: current_user - ) - end - end - - @project - rescue => ex - @project.errors.add(:base, "Can't save project. Please try again later") - @project - end - - protected - - def deny_namespace - @project.errors.add(:namespace, "is not valid") - end - - def allowed_namespace?(user, namespace_id) - namespace = Namespace.find_by_id(namespace_id) - current_user.can?(:manage_namespace, namespace) - end - end -end diff --git a/app/contexts/projects/fork_context.rb b/app/contexts/projects/fork_context.rb deleted file mode 100644 index fbc6722..0000000 --- a/app/contexts/projects/fork_context.rb +++ /dev/null @@ -1,44 +0,0 @@ -module Projects - class ForkContext < BaseContext - include Gitlab::ShellAdapter - - def initialize(project, user) - @from_project, @current_user = project, user - end - - def execute - project = @from_project.dup - project.name = @from_project.name - project.path = @from_project.path - project.namespace = current_user.namespace - project.creator = current_user - - # If the project cannot save, we do not want to trigger the project destroy - # as this can have the side effect of deleting a repo attached to an existing - # project with the same name and namespace - if project.valid? - begin - Project.transaction do - #First save the DB entries as they can be rolled back if the repo fork fails - project.build_forked_project_link(forked_to_project_id: project.id, forked_from_project_id: @from_project.id) - if project.save - project.users_projects.create(project_access: UsersProject::MASTER, user: current_user) - end - #Now fork the repo - unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path) - raise "forking failed in gitlab-shell" - end - project.ensure_satellite_exists - end - rescue => ex - project.errors.add(:base, "Fork transaction failed.") - project.destroy - end - else - project.errors.add(:base, "Invalid fork destination") - end - project - - end - end -end diff --git a/app/contexts/projects/transfer_context.rb b/app/contexts/projects/transfer_context.rb deleted file mode 100644 index 3011984..0000000 --- a/app/contexts/projects/transfer_context.rb +++ /dev/null @@ -1,22 +0,0 @@ -module Projects - class TransferContext < BaseContext - def execute(role = :default) - namespace_id = params[:project].delete(:namespace_id) - allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin - - if allowed_transfer && namespace_id.present? - if namespace_id.to_i != project.namespace_id - # Transfer to someone namespace - namespace = Namespace.find(namespace_id) - project.transfer(namespace) - end - end - - rescue ProjectTransferService::TransferError => ex - project.reload - project.errors.add(:namespace_id, ex.message) - false - end - end -end - diff --git a/app/contexts/projects/update_context.rb b/app/contexts/projects/update_context.rb deleted file mode 100644 index 94de10d..0000000 --- a/app/contexts/projects/update_context.rb +++ /dev/null @@ -1,19 +0,0 @@ -module Projects - class UpdateContext < BaseContext - def execute(role = :default) - params[:project].delete(:namespace_id) - # check that user is allowed to set specified visibility_level - unless can?(current_user, :change_visibility_level, project) && Gitlab::VisibilityLevel.allowed_for?(current_user, params[:project][:visibility_level]) - params[:project].delete(:visibility_level) - end - - new_branch = params[:project].delete(:default_branch) - - if project.repository.exists? && new_branch && new_branch != project.default_branch - project.change_head(new_branch) - end - - project.update_attributes(params[:project], as: role) - end - end -end diff --git a/app/contexts/search/global_context.rb b/app/contexts/search/global_context.rb deleted file mode 100644 index 74e7460..0000000 --- a/app/contexts/search/global_context.rb +++ /dev/null @@ -1,40 +0,0 @@ -module Search - class GlobalContext - attr_accessor :current_user, :params - - def initialize(user, params) - @current_user, @params = user, params.dup - end - - def execute - query = params[:search] - query = Shellwords.shellescape(query) if query.present? - return result unless query.present? - - authorized_projects_ids = [] - authorized_projects_ids += current_user.authorized_projects.pluck(:id) if current_user - authorized_projects_ids += Project.public_or_internal_only(current_user).pluck(:id) - - group = Group.find_by_id(params[:group_id]) if params[:group_id].present? - projects = Project.where(id: authorized_projects_ids) - projects = projects.where(namespace_id: group.id) if group - projects = projects.search(query) - project_ids = projects.pluck(:id) - - result[:projects] = projects.limit(20) - result[:merge_requests] = MergeRequest.in_projects(project_ids).search(query).order('updated_at DESC').limit(20) - result[:issues] = Issue.where(project_id: project_ids).search(query).order('updated_at DESC').limit(20) - result[:total_results] = %w(projects issues merge_requests).sum { |items| result[items.to_sym].size } - result - end - - def result - @result ||= { - projects: [], - merge_requests: [], - issues: [], - total_results: 0, - } - end - end -end diff --git a/app/contexts/search/project_context.rb b/app/contexts/search/project_context.rb deleted file mode 100644 index 690652b..0000000 --- a/app/contexts/search/project_context.rb +++ /dev/null @@ -1,37 +0,0 @@ -module Search - class ProjectContext - attr_accessor :project, :current_user, :params - - def initialize(project, user, params) - @project, @current_user, @params = project, user, params.dup - end - - def execute - query = params[:search] - query = Shellwords.shellescape(query) if query.present? - return result unless query.present? - - if params[:search_code].present? - blobs = project.repository.search_files(query, params[:repository_ref]) unless project.empty_repo? - blobs = Kaminari.paginate_array(blobs).page(params[:page]).per(20) - result[:blobs] = blobs - result[:total_results] = blobs.total_count - else - result[:merge_requests] = project.merge_requests.search(query).order('updated_at DESC').limit(20) - result[:issues] = project.issues.search(query).order('updated_at DESC').limit(20) - result[:total_results] = %w(issues merge_requests).sum { |items| result[items.to_sym].size } - end - - result - end - - def result - @result ||= { - merge_requests: [], - issues: [], - blobs: [], - total_results: 0, - } - end - end -end diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 7e3e29f..ea20595 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -19,7 +19,7 @@ class Admin::ProjectsController < Admin::ApplicationController end def transfer - result = ::Projects::TransferContext.new(@project, current_user, project: params).execute(:admin) + result = ::Projects::TransferService.new(@project, current_user, project: params).execute(:admin) if result redirect_to [:admin, @project] diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index fc9807e..2aa7347 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -13,7 +13,7 @@ class Projects::BlobController < Projects::ApplicationController end def destroy - result = Files::DeleteContext.new(@project, current_user, params, @ref, @path).execute + result = Files::DeleteService.new(@project, current_user, params, @ref, @path).execute if result[:status] == :success flash[:notice] = "Your changes have been successfully committed" diff --git a/app/controllers/projects/edit_tree_controller.rb b/app/controllers/projects/edit_tree_controller.rb index 3921273..aa46313 100644 --- a/app/controllers/projects/edit_tree_controller.rb +++ b/app/controllers/projects/edit_tree_controller.rb @@ -7,7 +7,7 @@ class Projects::EditTreeController < Projects::BaseTreeController end def update - result = Files::UpdateContext.new(@project, current_user, params, @ref, @path).execute + result = Files::UpdateService.new(@project, current_user, params, @ref, @path).execute if result[:status] == :success flash[:notice] = "Your changes have been successfully committed" diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 83ff968..770fcca 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -89,7 +89,7 @@ class Projects::IssuesController < Projects::ApplicationController end def bulk_update - result = Issues::BulkUpdateContext.new(project, current_user, params).execute + result = Issues::BulkUpdateService.new(project, current_user, params).execute redirect_to :back, notice: "#{result[:count]} issues updated" end diff --git a/app/controllers/projects/new_tree_controller.rb b/app/controllers/projects/new_tree_controller.rb index 933a0cb..2f3647a 100644 --- a/app/controllers/projects/new_tree_controller.rb +++ b/app/controllers/projects/new_tree_controller.rb @@ -6,7 +6,7 @@ class Projects::NewTreeController < Projects::BaseTreeController def update file_path = File.join(@path, File.basename(params[:file_name])) - result = Files::CreateContext.new(@project, current_user, params, @ref, file_path).execute + result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute if result[:status] == :success flash[:notice] = "Your changes have been successfully committed" diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 261841f..9c9c2de 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -5,7 +5,7 @@ class Projects::NotesController < Projects::ApplicationController before_filter :authorize_admin_note!, only: [:update, :destroy] def index - @notes = Notes::LoadContext.new(project, current_user, params).execute + @notes = Notes::LoadService.new(project, current_user, params).execute notes_json = { notes: [] } @@ -20,7 +20,7 @@ class Projects::NotesController < Projects::ApplicationController end def create - @note = Notes::CreateContext.new(project, current_user, params).execute + @note = Notes::CreateService.new(project, current_user, params).execute respond_to do |format| format.json { render_note_json(@note) } diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index e1c55e7..6ec109b 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -20,7 +20,7 @@ class ProjectsController < ApplicationController end def create - @project = ::Projects::CreateContext.new(current_user, params[:project]).execute + @project = ::Projects::CreateService.new(current_user, params[:project]).execute respond_to do |format| flash[:notice] = 'Project was successfully created.' if @project.saved? @@ -36,7 +36,7 @@ class ProjectsController < ApplicationController end def update - status = ::Projects::UpdateContext.new(@project, current_user, params).execute + status = ::Projects::UpdateService.new(@project, current_user, params).execute respond_to do |format| if status @@ -51,7 +51,7 @@ class ProjectsController < ApplicationController end def transfer - ::Projects::TransferContext.new(project, current_user, params).execute + ::Projects::TransferService.new(project, current_user, params).execute end def show @@ -89,7 +89,7 @@ class ProjectsController < ApplicationController end def fork - @forked_project = ::Projects::ForkContext.new(project, current_user).execute + @forked_project = ::Projects::ForkService.new(project, current_user).execute respond_to do |format| format.html do diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index ba8f08c..e853c22 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -5,9 +5,9 @@ class SearchController < ApplicationController if @project return access_denied! unless can?(current_user, :download_code, @project) - @search_results = Search::ProjectContext.new(@project, current_user, params).execute + @search_results = Search::ProjectService.new(@project, current_user, params).execute else - @search_results = Search::GlobalContext.new(current_user, params).execute + @search_results = Search::GlobalService.new(current_user, params).execute end end end diff --git a/app/services/base_service.rb b/app/services/base_service.rb new file mode 100644 index 0000000..610f047 --- /dev/null +++ b/app/services/base_service.rb @@ -0,0 +1,19 @@ +class BaseService + attr_accessor :project, :current_user, :params + + def initialize(project, user, params) + @project, @current_user, @params = project, user, params.dup + end + + def abilities + @abilities ||= begin + abilities = Six.new + abilities << Ability + abilities + end + end + + def can?(object, action, subject) + abilities.allowed?(object, action, subject) + end +end diff --git a/app/services/files/base_service.rb b/app/services/files/base_service.rb new file mode 100644 index 0000000..f1765d3 --- /dev/null +++ b/app/services/files/base_service.rb @@ -0,0 +1,31 @@ +module Files + class BaseService < ::BaseService + attr_reader :ref, :path + + def initialize(project, user, params, ref, path = nil) + @project, @current_user, @params = project, user, params.dup + @ref = ref + @path = path + end + + private + + def error(message) + { + error: message, + status: :error + } + end + + def success + { + error: '', + status: :success + } + end + + def repository + project.repository + end + end +end diff --git a/app/services/files/create_service.rb b/app/services/files/create_service.rb new file mode 100644 index 0000000..361bb45 --- /dev/null +++ b/app/services/files/create_service.rb @@ -0,0 +1,46 @@ +require_relative "base_context" + +module Files + class CreateService < BaseService + def execute + allowed = if project.protected_branch?(ref) + can?(current_user, :push_code_to_protected_branches, project) + else + can?(current_user, :push_code, project) + end + + unless allowed + return error("You are not allowed to create file in this branch") + end + + unless repository.branch_names.include?(ref) + return error("You can only create files if you are on top of a branch") + end + + file_name = File.basename(path) + file_path = path + + unless file_name =~ Gitlab::Regex.path_regex + return error("Your changes could not be committed, because file name contains not allowed characters") + end + + blob = repository.blob_at(ref, file_path) + + if blob + return error("Your changes could not be committed, because file with such name exists") + end + + new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, file_path) + created_successfully = new_file_action.commit!( + params[:content], + params[:commit_message] + ) + + if created_successfully + success + else + error("Your changes could not be committed, because the file has been changed") + end + end + end +end diff --git a/app/services/files/delete_service.rb b/app/services/files/delete_service.rb new file mode 100644 index 0000000..30f1f25 --- /dev/null +++ b/app/services/files/delete_service.rb @@ -0,0 +1,40 @@ +require_relative "base_context" + +module Files + class DeleteService < BaseService + def execute + allowed = if project.protected_branch?(ref) + can?(current_user, :push_code_to_protected_branches, project) + else + can?(current_user, :push_code, project) + end + + unless allowed + return error("You are not allowed to push into this branch") + end + + unless repository.branch_names.include?(ref) + return error("You can only create files if you are on top of a branch") + end + + blob = repository.blob_at(ref, path) + + unless blob + return error("You can only edit text files") + end + + delete_file_action = Gitlab::Satellite::DeleteFileAction.new(current_user, project, ref, path) + + deleted_successfully = delete_file_action.commit!( + nil, + params[:commit_message] + ) + + if deleted_successfully + success + else + error("Your changes could not be committed, because the file has been changed") + end + end + end +end diff --git a/app/services/files/update_service.rb b/app/services/files/update_service.rb new file mode 100644 index 0000000..20ca1ff --- /dev/null +++ b/app/services/files/update_service.rb @@ -0,0 +1,39 @@ +require_relative "base_context" + +module Files + class UpdateService < BaseService + def execute + allowed = if project.protected_branch?(ref) + can?(current_user, :push_code_to_protected_branches, project) + else + can?(current_user, :push_code, project) + end + + unless allowed + return error("You are not allowed to push into this branch") + end + + unless repository.branch_names.include?(ref) + return error("You can only create files if you are on top of a branch") + end + + blob = repository.blob_at(ref, path) + + unless blob + return error("You can only edit text files") + end + + new_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path) + created_successfully = new_file_action.commit!( + params[:content], + params[:commit_message] + ) + + if created_successfully + success + else + error("Your changes could not be committed, because the file has been changed") + end + end + end +end diff --git a/app/services/issues/bulk_update_service.rb b/app/services/issues/bulk_update_service.rb new file mode 100644 index 0000000..f72a346 --- /dev/null +++ b/app/services/issues/bulk_update_service.rb @@ -0,0 +1,39 @@ +module Issues + class BulkUpdateService < BaseService + def execute + update_data = params[:update] + + issues_ids = update_data[:issues_ids].split(",") + milestone_id = update_data[:milestone_id] + assignee_id = update_data[:assignee_id] + status = update_data[:status] + + new_state = nil + + if status.present? + if status == 'closed' + new_state = :close + else + new_state = :reopen + end + end + + opts = {} + opts[:milestone_id] = milestone_id if milestone_id.present? + opts[:assignee_id] = assignee_id if assignee_id.present? + + issues = Issue.where(id: issues_ids) + issues = issues.select { |issue| can?(current_user, :modify_issue, issue) } + + issues.each do |issue| + issue.update_attributes(opts) + issue.send new_state if new_state + end + + { + count: issues.count, + success: !issues.count.zero? + } + end + end +end diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb new file mode 100644 index 0000000..fb87e17 --- /dev/null +++ b/app/services/notes/create_service.rb @@ -0,0 +1,10 @@ +module Notes + class CreateService < BaseService + def execute + note = project.notes.new(params[:note]) + note.author = current_user + note.save + note + end + end +end diff --git a/app/services/notes/load_service.rb b/app/services/notes/load_service.rb new file mode 100644 index 0000000..f7ad7d6 --- /dev/null +++ b/app/services/notes/load_service.rb @@ -0,0 +1,20 @@ +module Notes + class LoadService < BaseService + def execute + target_type = params[:target_type] + target_id = params[:target_id] + + + @notes = case target_type + when "commit" + project.notes.for_commit_id(target_id).not_inline.fresh + when "issue" + project.issues.find(target_id).notes.inc_author.fresh + when "merge_request" + project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh + when "snippet" + project.snippets.find(target_id).notes.fresh + end + end + end +end diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb new file mode 100644 index 0000000..033be8f --- /dev/null +++ b/app/services/projects/create_service.rb @@ -0,0 +1,80 @@ +module Projects + class CreateService < BaseService + def initialize(user, params) + @current_user, @params = user, params.dup + end + + def execute + # get namespace id + namespace_id = params.delete(:namespace_id) + + # check that user is allowed to set specified visibility_level + unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) + params.delete(:visibility_level) + end + + # Load default feature settings + default_features = Gitlab.config.gitlab.default_projects_features + + default_opts = { + issues_enabled: default_features.issues, + wiki_enabled: default_features.wiki, + wall_enabled: default_features.wall, + snippets_enabled: default_features.snippets, + merge_requests_enabled: default_features.merge_requests, + visibility_level: default_features.visibility_level + }.stringify_keys + + @project = Project.new(default_opts.merge(params)) + + # Parametrize path for project + # + # Ex. + # 'GitLab HQ'.parameterize => "gitlab-hq" + # + @project.path = @project.name.dup.parameterize unless @project.path.present? + + + if namespace_id + # Find matching namespace and check if it allowed + # for current user if namespace_id passed. + if allowed_namespace?(current_user, namespace_id) + @project.namespace_id = namespace_id + else + deny_namespace + return @project + end + else + # Set current user namespace if namespace_id is nil + @project.namespace_id = current_user.namespace_id + end + + @project.creator = current_user + + if @project.save + unless @project.group + @project.users_projects.create( + project_access: UsersProject::MASTER, + user: current_user + ) + end + end + + @project + rescue => ex + @project.errors.add(:base, "Can't save project. Please try again later") + @project + end + + protected + + def deny_namespace + @project.errors.add(:namespace, "is not valid") + end + + def allowed_namespace?(user, namespace_id) + namespace = Namespace.find_by_id(namespace_id) + current_user.can?(:manage_namespace, namespace) + end + end +end diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb new file mode 100644 index 0000000..2f1c7b1 --- /dev/null +++ b/app/services/projects/fork_service.rb @@ -0,0 +1,44 @@ +module Projects + class ForkService < BaseService + include Gitlab::ShellAdapter + + def initialize(project, user) + @from_project, @current_user = project, user + end + + def execute + project = @from_project.dup + project.name = @from_project.name + project.path = @from_project.path + project.namespace = current_user.namespace + project.creator = current_user + + # If the project cannot save, we do not want to trigger the project destroy + # as this can have the side effect of deleting a repo attached to an existing + # project with the same name and namespace + if project.valid? + begin + Project.transaction do + #First save the DB entries as they can be rolled back if the repo fork fails + project.build_forked_project_link(forked_to_project_id: project.id, forked_from_project_id: @from_project.id) + if project.save + project.users_projects.create(project_access: UsersProject::MASTER, user: current_user) + end + #Now fork the repo + unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path) + raise "forking failed in gitlab-shell" + end + project.ensure_satellite_exists + end + rescue => ex + project.errors.add(:base, "Fork transaction failed.") + project.destroy + end + else + project.errors.add(:base, "Invalid fork destination") + end + project + + end + end +end diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb new file mode 100644 index 0000000..f8e27f6 --- /dev/null +++ b/app/services/projects/transfer_service.rb @@ -0,0 +1,22 @@ +module Projects + class TransferService < BaseService + def execute(role = :default) + namespace_id = params[:project].delete(:namespace_id) + allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin + + if allowed_transfer && namespace_id.present? + if namespace_id.to_i != project.namespace_id + # Transfer to someone namespace + namespace = Namespace.find(namespace_id) + project.transfer(namespace) + end + end + + rescue ProjectTransferService::TransferError => ex + project.reload + project.errors.add(:namespace_id, ex.message) + false + end + end +end + diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb new file mode 100644 index 0000000..d9d371d --- /dev/null +++ b/app/services/projects/update_service.rb @@ -0,0 +1,19 @@ +module Projects + class UpdateService < BaseService + def execute(role = :default) + params[:project].delete(:namespace_id) + # check that user is allowed to set specified visibility_level + unless can?(current_user, :change_visibility_level, project) && Gitlab::VisibilityLevel.allowed_for?(current_user, params[:project][:visibility_level]) + params[:project].delete(:visibility_level) + end + + new_branch = params[:project].delete(:default_branch) + + if project.repository.exists? && new_branch && new_branch != project.default_branch + project.change_head(new_branch) + end + + project.update_attributes(params[:project], as: role) + end + end +end diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb new file mode 100644 index 0000000..c5ca332 --- /dev/null +++ b/app/services/search/global_service.rb @@ -0,0 +1,40 @@ +module Search + class GlobalService + attr_accessor :current_user, :params + + def initialize(user, params) + @current_user, @params = user, params.dup + end + + def execute + query = params[:search] + query = Shellwords.shellescape(query) if query.present? + return result unless query.present? + + authorized_projects_ids = [] + authorized_projects_ids += current_user.authorized_projects.pluck(:id) if current_user + authorized_projects_ids += Project.public_or_internal_only(current_user).pluck(:id) + + group = Group.find_by_id(params[:group_id]) if params[:group_id].present? + projects = Project.where(id: authorized_projects_ids) + projects = projects.where(namespace_id: group.id) if group + projects = projects.search(query) + project_ids = projects.pluck(:id) + + result[:projects] = projects.limit(20) + result[:merge_requests] = MergeRequest.in_projects(project_ids).search(query).order('updated_at DESC').limit(20) + result[:issues] = Issue.where(project_id: project_ids).search(query).order('updated_at DESC').limit(20) + result[:total_results] = %w(projects issues merge_requests).sum { |items| result[items.to_sym].size } + result + end + + def result + @result ||= { + projects: [], + merge_requests: [], + issues: [], + total_results: 0, + } + end + end +end diff --git a/app/services/search/project_service.rb b/app/services/search/project_service.rb new file mode 100644 index 0000000..3ebaafc --- /dev/null +++ b/app/services/search/project_service.rb @@ -0,0 +1,37 @@ +module Search + class ProjectService + attr_accessor :project, :current_user, :params + + def initialize(project, user, params) + @project, @current_user, @params = project, user, params.dup + end + + def execute + query = params[:search] + query = Shellwords.shellescape(query) if query.present? + return result unless query.present? + + if params[:search_code].present? + blobs = project.repository.search_files(query, params[:repository_ref]) unless project.empty_repo? + blobs = Kaminari.paginate_array(blobs).page(params[:page]).per(20) + result[:blobs] = blobs + result[:total_results] = blobs.total_count + else + result[:merge_requests] = project.merge_requests.search(query).order('updated_at DESC').limit(20) + result[:issues] = project.issues.search(query).order('updated_at DESC').limit(20) + result[:total_results] = %w(issues merge_requests).sum { |items| result[items.to_sym].size } + end + + result + end + + def result + @result ||= { + merge_requests: [], + issues: [], + blobs: [], + total_results: 0, + } + end + end +end -- libgit2 0.21.2