Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2014-01-16 21:03:42 +0400
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2014-01-16 21:03:42 +0400
commit1d2bdb4d5880bb1ad39b62c81ff2971aa0cb3798 (patch)
tree8ac3215b2c25cb57b5f2198fd4d85c7bad968c2b /app/services
parentdba982403b7b894d2096ea61b89a247060eefe57 (diff)
Move all Context classes into Services
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Diffstat (limited to 'app/services')
-rw-r--r--app/services/base_service.rb19
-rw-r--r--app/services/files/base_service.rb31
-rw-r--r--app/services/files/create_service.rb46
-rw-r--r--app/services/files/delete_service.rb40
-rw-r--r--app/services/files/update_service.rb39
-rw-r--r--app/services/issues/bulk_update_service.rb39
-rw-r--r--app/services/notes/create_service.rb10
-rw-r--r--app/services/notes/load_service.rb20
-rw-r--r--app/services/projects/create_service.rb80
-rw-r--r--app/services/projects/fork_service.rb44
-rw-r--r--app/services/projects/transfer_service.rb22
-rw-r--r--app/services/projects/update_service.rb19
-rw-r--r--app/services/search/global_service.rb40
-rw-r--r--app/services/search/project_service.rb37
14 files changed, 486 insertions, 0 deletions
diff --git a/app/services/base_service.rb b/app/services/base_service.rb
new file mode 100644
index 00000000000..610f0474872
--- /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 00000000000..f1765d38976
--- /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 00000000000..361bb458889
--- /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 00000000000..30f1f2512cb
--- /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 00000000000..20ca1ff37d5
--- /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 00000000000..f72a346af6f
--- /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 00000000000..fb87e175933
--- /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 00000000000..f7ad7d60a3a
--- /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 00000000000..033be8f9ed6
--- /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 00000000000..2f1c7b18aa0
--- /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 00000000000..f8e27f6f1c6
--- /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 00000000000..d9d371da5c4
--- /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 00000000000..c5ca3322362
--- /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 00000000000..3ebaafc752c
--- /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