Commit f0d2d28118354b6362988687757b63dc7be611e5
Exists in
spb-stable
and in
3 other branches
Merge branch 'refactoring/context_into_services' into 'master'
Refactoring context Into services To prevent confusion where to write logic. Context or Service?
Showing
50 changed files
with
985 additions
and
985 deletions
Show diff stats
app/contexts/base_context.rb
@@ -1,19 +0,0 @@ | @@ -1,19 +0,0 @@ | ||
1 | -class BaseContext | ||
2 | - attr_accessor :project, :current_user, :params | ||
3 | - | ||
4 | - def initialize(project, user, params) | ||
5 | - @project, @current_user, @params = project, user, params.dup | ||
6 | - end | ||
7 | - | ||
8 | - def abilities | ||
9 | - @abilities ||= begin | ||
10 | - abilities = Six.new | ||
11 | - abilities << Ability | ||
12 | - abilities | ||
13 | - end | ||
14 | - end | ||
15 | - | ||
16 | - def can?(object, action, subject) | ||
17 | - abilities.allowed?(object, action, subject) | ||
18 | - end | ||
19 | -end |
app/contexts/files/base_context.rb
@@ -1,31 +0,0 @@ | @@ -1,31 +0,0 @@ | ||
1 | -module Files | ||
2 | - class BaseContext < ::BaseContext | ||
3 | - attr_reader :ref, :path | ||
4 | - | ||
5 | - def initialize(project, user, params, ref, path = nil) | ||
6 | - @project, @current_user, @params = project, user, params.dup | ||
7 | - @ref = ref | ||
8 | - @path = path | ||
9 | - end | ||
10 | - | ||
11 | - private | ||
12 | - | ||
13 | - def error(message) | ||
14 | - { | ||
15 | - error: message, | ||
16 | - status: :error | ||
17 | - } | ||
18 | - end | ||
19 | - | ||
20 | - def success | ||
21 | - { | ||
22 | - error: '', | ||
23 | - status: :success | ||
24 | - } | ||
25 | - end | ||
26 | - | ||
27 | - def repository | ||
28 | - project.repository | ||
29 | - end | ||
30 | - end | ||
31 | -end |
app/contexts/files/create_context.rb
@@ -1,47 +0,0 @@ | @@ -1,47 +0,0 @@ | ||
1 | -require_relative "base_context" | ||
2 | - | ||
3 | -module Files | ||
4 | - class CreateContext < BaseContext | ||
5 | - def execute | ||
6 | - allowed = if project.protected_branch?(ref) | ||
7 | - can?(current_user, :push_code_to_protected_branches, project) | ||
8 | - else | ||
9 | - can?(current_user, :push_code, project) | ||
10 | - end | ||
11 | - | ||
12 | - unless allowed | ||
13 | - return error("You are not allowed to create file in this branch") | ||
14 | - end | ||
15 | - | ||
16 | - unless repository.branch_names.include?(ref) | ||
17 | - return error("You can only create files if you are on top of a branch") | ||
18 | - end | ||
19 | - | ||
20 | - file_name = File.basename(path) | ||
21 | - file_path = path | ||
22 | - | ||
23 | - unless file_name =~ Gitlab::Regex.path_regex | ||
24 | - return error("Your changes could not be committed, because file name contains not allowed characters") | ||
25 | - end | ||
26 | - | ||
27 | - blob = repository.blob_at(ref, file_path) | ||
28 | - | ||
29 | - if blob | ||
30 | - return error("Your changes could not be committed, because file with such name exists") | ||
31 | - end | ||
32 | - | ||
33 | - new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, file_path) | ||
34 | - created_successfully = new_file_action.commit!( | ||
35 | - params[:content], | ||
36 | - params[:commit_message], | ||
37 | - params[:encoding] | ||
38 | - ) | ||
39 | - | ||
40 | - if created_successfully | ||
41 | - success | ||
42 | - else | ||
43 | - error("Your changes could not be committed, because the file has been changed") | ||
44 | - end | ||
45 | - end | ||
46 | - end | ||
47 | -end |
app/contexts/files/delete_context.rb
@@ -1,40 +0,0 @@ | @@ -1,40 +0,0 @@ | ||
1 | -require_relative "base_context" | ||
2 | - | ||
3 | -module Files | ||
4 | - class DeleteContext < BaseContext | ||
5 | - def execute | ||
6 | - allowed = if project.protected_branch?(ref) | ||
7 | - can?(current_user, :push_code_to_protected_branches, project) | ||
8 | - else | ||
9 | - can?(current_user, :push_code, project) | ||
10 | - end | ||
11 | - | ||
12 | - unless allowed | ||
13 | - return error("You are not allowed to push into this branch") | ||
14 | - end | ||
15 | - | ||
16 | - unless repository.branch_names.include?(ref) | ||
17 | - return error("You can only create files if you are on top of a branch") | ||
18 | - end | ||
19 | - | ||
20 | - blob = repository.blob_at(ref, path) | ||
21 | - | ||
22 | - unless blob | ||
23 | - return error("You can only edit text files") | ||
24 | - end | ||
25 | - | ||
26 | - delete_file_action = Gitlab::Satellite::DeleteFileAction.new(current_user, project, ref, path) | ||
27 | - | ||
28 | - deleted_successfully = delete_file_action.commit!( | ||
29 | - nil, | ||
30 | - params[:commit_message] | ||
31 | - ) | ||
32 | - | ||
33 | - if deleted_successfully | ||
34 | - success | ||
35 | - else | ||
36 | - error("Your changes could not be committed, because the file has been changed") | ||
37 | - end | ||
38 | - end | ||
39 | - end | ||
40 | -end |
app/contexts/files/update_context.rb
@@ -1,40 +0,0 @@ | @@ -1,40 +0,0 @@ | ||
1 | -require_relative "base_context" | ||
2 | - | ||
3 | -module Files | ||
4 | - class UpdateContext < BaseContext | ||
5 | - def execute | ||
6 | - allowed = if project.protected_branch?(ref) | ||
7 | - can?(current_user, :push_code_to_protected_branches, project) | ||
8 | - else | ||
9 | - can?(current_user, :push_code, project) | ||
10 | - end | ||
11 | - | ||
12 | - unless allowed | ||
13 | - return error("You are not allowed to push into this branch") | ||
14 | - end | ||
15 | - | ||
16 | - unless repository.branch_names.include?(ref) | ||
17 | - return error("You can only create files if you are on top of a branch") | ||
18 | - end | ||
19 | - | ||
20 | - blob = repository.blob_at(ref, path) | ||
21 | - | ||
22 | - unless blob | ||
23 | - return error("You can only edit text files") | ||
24 | - end | ||
25 | - | ||
26 | - edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path) | ||
27 | - created_successfully = edit_file_action.commit!( | ||
28 | - params[:content], | ||
29 | - params[:commit_message], | ||
30 | - params[:encoding] | ||
31 | - ) | ||
32 | - | ||
33 | - if created_successfully | ||
34 | - success | ||
35 | - else | ||
36 | - error("Your changes could not be committed, because the file has been changed") | ||
37 | - end | ||
38 | - end | ||
39 | - end | ||
40 | -end |
app/contexts/issues/bulk_update_context.rb
@@ -1,39 +0,0 @@ | @@ -1,39 +0,0 @@ | ||
1 | -module Issues | ||
2 | - class BulkUpdateContext < BaseContext | ||
3 | - def execute | ||
4 | - update_data = params[:update] | ||
5 | - | ||
6 | - issues_ids = update_data[:issues_ids].split(",") | ||
7 | - milestone_id = update_data[:milestone_id] | ||
8 | - assignee_id = update_data[:assignee_id] | ||
9 | - status = update_data[:status] | ||
10 | - | ||
11 | - new_state = nil | ||
12 | - | ||
13 | - if status.present? | ||
14 | - if status == 'closed' | ||
15 | - new_state = :close | ||
16 | - else | ||
17 | - new_state = :reopen | ||
18 | - end | ||
19 | - end | ||
20 | - | ||
21 | - opts = {} | ||
22 | - opts[:milestone_id] = milestone_id if milestone_id.present? | ||
23 | - opts[:assignee_id] = assignee_id if assignee_id.present? | ||
24 | - | ||
25 | - issues = Issue.where(id: issues_ids) | ||
26 | - issues = issues.select { |issue| can?(current_user, :modify_issue, issue) } | ||
27 | - | ||
28 | - issues.each do |issue| | ||
29 | - issue.update_attributes(opts) | ||
30 | - issue.send new_state if new_state | ||
31 | - end | ||
32 | - | ||
33 | - { | ||
34 | - count: issues.count, | ||
35 | - success: !issues.count.zero? | ||
36 | - } | ||
37 | - end | ||
38 | - end | ||
39 | -end |
app/contexts/notes/create_context.rb
app/contexts/notes/load_context.rb
@@ -1,20 +0,0 @@ | @@ -1,20 +0,0 @@ | ||
1 | -module Notes | ||
2 | - class LoadContext < BaseContext | ||
3 | - def execute | ||
4 | - target_type = params[:target_type] | ||
5 | - target_id = params[:target_id] | ||
6 | - | ||
7 | - | ||
8 | - @notes = case target_type | ||
9 | - when "commit" | ||
10 | - project.notes.for_commit_id(target_id).not_inline.fresh | ||
11 | - when "issue" | ||
12 | - project.issues.find(target_id).notes.inc_author.fresh | ||
13 | - when "merge_request" | ||
14 | - project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh | ||
15 | - when "snippet" | ||
16 | - project.snippets.find(target_id).notes.fresh | ||
17 | - end | ||
18 | - end | ||
19 | - end | ||
20 | -end |
app/contexts/projects/create_context.rb
@@ -1,80 +0,0 @@ | @@ -1,80 +0,0 @@ | ||
1 | -module Projects | ||
2 | - class CreateContext < BaseContext | ||
3 | - def initialize(user, params) | ||
4 | - @current_user, @params = user, params.dup | ||
5 | - end | ||
6 | - | ||
7 | - def execute | ||
8 | - # get namespace id | ||
9 | - namespace_id = params.delete(:namespace_id) | ||
10 | - | ||
11 | - # check that user is allowed to set specified visibility_level | ||
12 | - unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) | ||
13 | - params.delete(:visibility_level) | ||
14 | - end | ||
15 | - | ||
16 | - # Load default feature settings | ||
17 | - default_features = Gitlab.config.gitlab.default_projects_features | ||
18 | - | ||
19 | - default_opts = { | ||
20 | - issues_enabled: default_features.issues, | ||
21 | - wiki_enabled: default_features.wiki, | ||
22 | - wall_enabled: default_features.wall, | ||
23 | - snippets_enabled: default_features.snippets, | ||
24 | - merge_requests_enabled: default_features.merge_requests, | ||
25 | - visibility_level: default_features.visibility_level | ||
26 | - }.stringify_keys | ||
27 | - | ||
28 | - @project = Project.new(default_opts.merge(params)) | ||
29 | - | ||
30 | - # Parametrize path for project | ||
31 | - # | ||
32 | - # Ex. | ||
33 | - # 'GitLab HQ'.parameterize => "gitlab-hq" | ||
34 | - # | ||
35 | - @project.path = @project.name.dup.parameterize unless @project.path.present? | ||
36 | - | ||
37 | - | ||
38 | - if namespace_id | ||
39 | - # Find matching namespace and check if it allowed | ||
40 | - # for current user if namespace_id passed. | ||
41 | - if allowed_namespace?(current_user, namespace_id) | ||
42 | - @project.namespace_id = namespace_id | ||
43 | - else | ||
44 | - deny_namespace | ||
45 | - return @project | ||
46 | - end | ||
47 | - else | ||
48 | - # Set current user namespace if namespace_id is nil | ||
49 | - @project.namespace_id = current_user.namespace_id | ||
50 | - end | ||
51 | - | ||
52 | - @project.creator = current_user | ||
53 | - | ||
54 | - if @project.save | ||
55 | - unless @project.group | ||
56 | - @project.users_projects.create( | ||
57 | - project_access: UsersProject::MASTER, | ||
58 | - user: current_user | ||
59 | - ) | ||
60 | - end | ||
61 | - end | ||
62 | - | ||
63 | - @project | ||
64 | - rescue => ex | ||
65 | - @project.errors.add(:base, "Can't save project. Please try again later") | ||
66 | - @project | ||
67 | - end | ||
68 | - | ||
69 | - protected | ||
70 | - | ||
71 | - def deny_namespace | ||
72 | - @project.errors.add(:namespace, "is not valid") | ||
73 | - end | ||
74 | - | ||
75 | - def allowed_namespace?(user, namespace_id) | ||
76 | - namespace = Namespace.find_by_id(namespace_id) | ||
77 | - current_user.can?(:manage_namespace, namespace) | ||
78 | - end | ||
79 | - end | ||
80 | -end |
app/contexts/projects/fork_context.rb
@@ -1,44 +0,0 @@ | @@ -1,44 +0,0 @@ | ||
1 | -module Projects | ||
2 | - class ForkContext < BaseContext | ||
3 | - include Gitlab::ShellAdapter | ||
4 | - | ||
5 | - def initialize(project, user) | ||
6 | - @from_project, @current_user = project, user | ||
7 | - end | ||
8 | - | ||
9 | - def execute | ||
10 | - project = @from_project.dup | ||
11 | - project.name = @from_project.name | ||
12 | - project.path = @from_project.path | ||
13 | - project.namespace = current_user.namespace | ||
14 | - project.creator = current_user | ||
15 | - | ||
16 | - # If the project cannot save, we do not want to trigger the project destroy | ||
17 | - # as this can have the side effect of deleting a repo attached to an existing | ||
18 | - # project with the same name and namespace | ||
19 | - if project.valid? | ||
20 | - begin | ||
21 | - Project.transaction do | ||
22 | - #First save the DB entries as they can be rolled back if the repo fork fails | ||
23 | - project.build_forked_project_link(forked_to_project_id: project.id, forked_from_project_id: @from_project.id) | ||
24 | - if project.save | ||
25 | - project.users_projects.create(project_access: UsersProject::MASTER, user: current_user) | ||
26 | - end | ||
27 | - #Now fork the repo | ||
28 | - unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path) | ||
29 | - raise "forking failed in gitlab-shell" | ||
30 | - end | ||
31 | - project.ensure_satellite_exists | ||
32 | - end | ||
33 | - rescue => ex | ||
34 | - project.errors.add(:base, "Fork transaction failed.") | ||
35 | - project.destroy | ||
36 | - end | ||
37 | - else | ||
38 | - project.errors.add(:base, "Invalid fork destination") | ||
39 | - end | ||
40 | - project | ||
41 | - | ||
42 | - end | ||
43 | - end | ||
44 | -end |
app/contexts/projects/transfer_context.rb
@@ -1,22 +0,0 @@ | @@ -1,22 +0,0 @@ | ||
1 | -module Projects | ||
2 | - class TransferContext < BaseContext | ||
3 | - def execute(role = :default) | ||
4 | - namespace_id = params[:project].delete(:namespace_id) | ||
5 | - allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin | ||
6 | - | ||
7 | - if allowed_transfer && namespace_id.present? | ||
8 | - if namespace_id.to_i != project.namespace_id | ||
9 | - # Transfer to someone namespace | ||
10 | - namespace = Namespace.find(namespace_id) | ||
11 | - project.transfer(namespace) | ||
12 | - end | ||
13 | - end | ||
14 | - | ||
15 | - rescue ProjectTransferService::TransferError => ex | ||
16 | - project.reload | ||
17 | - project.errors.add(:namespace_id, ex.message) | ||
18 | - false | ||
19 | - end | ||
20 | - end | ||
21 | -end | ||
22 | - |
app/contexts/projects/update_context.rb
@@ -1,19 +0,0 @@ | @@ -1,19 +0,0 @@ | ||
1 | -module Projects | ||
2 | - class UpdateContext < BaseContext | ||
3 | - def execute(role = :default) | ||
4 | - params[:project].delete(:namespace_id) | ||
5 | - # check that user is allowed to set specified visibility_level | ||
6 | - unless can?(current_user, :change_visibility_level, project) && Gitlab::VisibilityLevel.allowed_for?(current_user, params[:project][:visibility_level]) | ||
7 | - params[:project].delete(:visibility_level) | ||
8 | - end | ||
9 | - | ||
10 | - new_branch = params[:project].delete(:default_branch) | ||
11 | - | ||
12 | - if project.repository.exists? && new_branch && new_branch != project.default_branch | ||
13 | - project.change_head(new_branch) | ||
14 | - end | ||
15 | - | ||
16 | - project.update_attributes(params[:project], as: role) | ||
17 | - end | ||
18 | - end | ||
19 | -end |
app/contexts/search/global_context.rb
@@ -1,40 +0,0 @@ | @@ -1,40 +0,0 @@ | ||
1 | -module Search | ||
2 | - class GlobalContext | ||
3 | - attr_accessor :current_user, :params | ||
4 | - | ||
5 | - def initialize(user, params) | ||
6 | - @current_user, @params = user, params.dup | ||
7 | - end | ||
8 | - | ||
9 | - def execute | ||
10 | - query = params[:search] | ||
11 | - query = Shellwords.shellescape(query) if query.present? | ||
12 | - return result unless query.present? | ||
13 | - | ||
14 | - authorized_projects_ids = [] | ||
15 | - authorized_projects_ids += current_user.authorized_projects.pluck(:id) if current_user | ||
16 | - authorized_projects_ids += Project.public_or_internal_only(current_user).pluck(:id) | ||
17 | - | ||
18 | - group = Group.find_by_id(params[:group_id]) if params[:group_id].present? | ||
19 | - projects = Project.where(id: authorized_projects_ids) | ||
20 | - projects = projects.where(namespace_id: group.id) if group | ||
21 | - projects = projects.search(query) | ||
22 | - project_ids = projects.pluck(:id) | ||
23 | - | ||
24 | - result[:projects] = projects.limit(20) | ||
25 | - result[:merge_requests] = MergeRequest.in_projects(project_ids).search(query).order('updated_at DESC').limit(20) | ||
26 | - result[:issues] = Issue.where(project_id: project_ids).search(query).order('updated_at DESC').limit(20) | ||
27 | - result[:total_results] = %w(projects issues merge_requests).sum { |items| result[items.to_sym].size } | ||
28 | - result | ||
29 | - end | ||
30 | - | ||
31 | - def result | ||
32 | - @result ||= { | ||
33 | - projects: [], | ||
34 | - merge_requests: [], | ||
35 | - issues: [], | ||
36 | - total_results: 0, | ||
37 | - } | ||
38 | - end | ||
39 | - end | ||
40 | -end |
app/contexts/search/project_context.rb
@@ -1,37 +0,0 @@ | @@ -1,37 +0,0 @@ | ||
1 | -module Search | ||
2 | - class ProjectContext | ||
3 | - attr_accessor :project, :current_user, :params | ||
4 | - | ||
5 | - def initialize(project, user, params) | ||
6 | - @project, @current_user, @params = project, user, params.dup | ||
7 | - end | ||
8 | - | ||
9 | - def execute | ||
10 | - query = params[:search] | ||
11 | - query = Shellwords.shellescape(query) if query.present? | ||
12 | - return result unless query.present? | ||
13 | - | ||
14 | - if params[:search_code].present? | ||
15 | - blobs = project.repository.search_files(query, params[:repository_ref]) unless project.empty_repo? | ||
16 | - blobs = Kaminari.paginate_array(blobs).page(params[:page]).per(20) | ||
17 | - result[:blobs] = blobs | ||
18 | - result[:total_results] = blobs.total_count | ||
19 | - else | ||
20 | - result[:merge_requests] = project.merge_requests.search(query).order('updated_at DESC').limit(20) | ||
21 | - result[:issues] = project.issues.search(query).order('updated_at DESC').limit(20) | ||
22 | - result[:total_results] = %w(issues merge_requests).sum { |items| result[items.to_sym].size } | ||
23 | - end | ||
24 | - | ||
25 | - result | ||
26 | - end | ||
27 | - | ||
28 | - def result | ||
29 | - @result ||= { | ||
30 | - merge_requests: [], | ||
31 | - issues: [], | ||
32 | - blobs: [], | ||
33 | - total_results: 0, | ||
34 | - } | ||
35 | - end | ||
36 | - end | ||
37 | -end |
app/controllers/admin/projects_controller.rb
@@ -19,7 +19,7 @@ class Admin::ProjectsController < Admin::ApplicationController | @@ -19,7 +19,7 @@ class Admin::ProjectsController < Admin::ApplicationController | ||
19 | end | 19 | end |
20 | 20 | ||
21 | def transfer | 21 | def transfer |
22 | - result = ::Projects::TransferContext.new(@project, current_user, project: params).execute(:admin) | 22 | + result = ::Projects::TransferService.new(@project, current_user, project: params).execute(:admin) |
23 | 23 | ||
24 | if result | 24 | if result |
25 | redirect_to [:admin, @project] | 25 | redirect_to [:admin, @project] |
app/controllers/projects/blob_controller.rb
@@ -13,7 +13,7 @@ class Projects::BlobController < Projects::ApplicationController | @@ -13,7 +13,7 @@ class Projects::BlobController < Projects::ApplicationController | ||
13 | end | 13 | end |
14 | 14 | ||
15 | def destroy | 15 | def destroy |
16 | - result = Files::DeleteContext.new(@project, current_user, params, @ref, @path).execute | 16 | + result = Files::DeleteService.new(@project, current_user, params, @ref, @path).execute |
17 | 17 | ||
18 | if result[:status] == :success | 18 | if result[:status] == :success |
19 | flash[:notice] = "Your changes have been successfully committed" | 19 | flash[:notice] = "Your changes have been successfully committed" |
app/controllers/projects/edit_tree_controller.rb
@@ -7,7 +7,7 @@ class Projects::EditTreeController < Projects::BaseTreeController | @@ -7,7 +7,7 @@ class Projects::EditTreeController < Projects::BaseTreeController | ||
7 | end | 7 | end |
8 | 8 | ||
9 | def update | 9 | def update |
10 | - result = Files::UpdateContext.new(@project, current_user, params, @ref, @path).execute | 10 | + result = Files::UpdateService.new(@project, current_user, params, @ref, @path).execute |
11 | 11 | ||
12 | if result[:status] == :success | 12 | if result[:status] == :success |
13 | flash[:notice] = "Your changes have been successfully committed" | 13 | flash[:notice] = "Your changes have been successfully committed" |
app/controllers/projects/issues_controller.rb
@@ -89,7 +89,7 @@ class Projects::IssuesController < Projects::ApplicationController | @@ -89,7 +89,7 @@ class Projects::IssuesController < Projects::ApplicationController | ||
89 | end | 89 | end |
90 | 90 | ||
91 | def bulk_update | 91 | def bulk_update |
92 | - result = Issues::BulkUpdateContext.new(project, current_user, params).execute | 92 | + result = Issues::BulkUpdateService.new(project, current_user, params).execute |
93 | redirect_to :back, notice: "#{result[:count]} issues updated" | 93 | redirect_to :back, notice: "#{result[:count]} issues updated" |
94 | end | 94 | end |
95 | 95 |
app/controllers/projects/new_tree_controller.rb
@@ -6,7 +6,7 @@ class Projects::NewTreeController < Projects::BaseTreeController | @@ -6,7 +6,7 @@ class Projects::NewTreeController < Projects::BaseTreeController | ||
6 | 6 | ||
7 | def update | 7 | def update |
8 | file_path = File.join(@path, File.basename(params[:file_name])) | 8 | file_path = File.join(@path, File.basename(params[:file_name])) |
9 | - result = Files::CreateContext.new(@project, current_user, params, @ref, file_path).execute | 9 | + result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute |
10 | 10 | ||
11 | if result[:status] == :success | 11 | if result[:status] == :success |
12 | flash[:notice] = "Your changes have been successfully committed" | 12 | flash[:notice] = "Your changes have been successfully committed" |
app/controllers/projects/notes_controller.rb
@@ -5,7 +5,7 @@ class Projects::NotesController < Projects::ApplicationController | @@ -5,7 +5,7 @@ class Projects::NotesController < Projects::ApplicationController | ||
5 | before_filter :authorize_admin_note!, only: [:update, :destroy] | 5 | before_filter :authorize_admin_note!, only: [:update, :destroy] |
6 | 6 | ||
7 | def index | 7 | def index |
8 | - @notes = Notes::LoadContext.new(project, current_user, params).execute | 8 | + @notes = Notes::LoadService.new(project, current_user, params).execute |
9 | 9 | ||
10 | notes_json = { notes: [] } | 10 | notes_json = { notes: [] } |
11 | 11 | ||
@@ -20,7 +20,7 @@ class Projects::NotesController < Projects::ApplicationController | @@ -20,7 +20,7 @@ class Projects::NotesController < Projects::ApplicationController | ||
20 | end | 20 | end |
21 | 21 | ||
22 | def create | 22 | def create |
23 | - @note = Notes::CreateContext.new(project, current_user, params).execute | 23 | + @note = Notes::CreateService.new(project, current_user, params).execute |
24 | 24 | ||
25 | respond_to do |format| | 25 | respond_to do |format| |
26 | format.json { render_note_json(@note) } | 26 | format.json { render_note_json(@note) } |
app/controllers/projects_controller.rb
@@ -20,7 +20,7 @@ class ProjectsController < ApplicationController | @@ -20,7 +20,7 @@ class ProjectsController < ApplicationController | ||
20 | end | 20 | end |
21 | 21 | ||
22 | def create | 22 | def create |
23 | - @project = ::Projects::CreateContext.new(current_user, params[:project]).execute | 23 | + @project = ::Projects::CreateService.new(current_user, params[:project]).execute |
24 | 24 | ||
25 | respond_to do |format| | 25 | respond_to do |format| |
26 | flash[:notice] = 'Project was successfully created.' if @project.saved? | 26 | flash[:notice] = 'Project was successfully created.' if @project.saved? |
@@ -36,7 +36,7 @@ class ProjectsController < ApplicationController | @@ -36,7 +36,7 @@ class ProjectsController < ApplicationController | ||
36 | end | 36 | end |
37 | 37 | ||
38 | def update | 38 | def update |
39 | - status = ::Projects::UpdateContext.new(@project, current_user, params).execute | 39 | + status = ::Projects::UpdateService.new(@project, current_user, params).execute |
40 | 40 | ||
41 | respond_to do |format| | 41 | respond_to do |format| |
42 | if status | 42 | if status |
@@ -51,7 +51,7 @@ class ProjectsController < ApplicationController | @@ -51,7 +51,7 @@ class ProjectsController < ApplicationController | ||
51 | end | 51 | end |
52 | 52 | ||
53 | def transfer | 53 | def transfer |
54 | - ::Projects::TransferContext.new(project, current_user, params).execute | 54 | + ::Projects::TransferService.new(project, current_user, params).execute |
55 | end | 55 | end |
56 | 56 | ||
57 | def show | 57 | def show |
@@ -89,7 +89,7 @@ class ProjectsController < ApplicationController | @@ -89,7 +89,7 @@ class ProjectsController < ApplicationController | ||
89 | end | 89 | end |
90 | 90 | ||
91 | def fork | 91 | def fork |
92 | - @forked_project = ::Projects::ForkContext.new(project, current_user).execute | 92 | + @forked_project = ::Projects::ForkService.new(project, current_user).execute |
93 | 93 | ||
94 | respond_to do |format| | 94 | respond_to do |format| |
95 | format.html do | 95 | format.html do |
app/controllers/search_controller.rb
@@ -5,9 +5,9 @@ class SearchController < ApplicationController | @@ -5,9 +5,9 @@ class SearchController < ApplicationController | ||
5 | 5 | ||
6 | if @project | 6 | if @project |
7 | return access_denied! unless can?(current_user, :download_code, @project) | 7 | return access_denied! unless can?(current_user, :download_code, @project) |
8 | - @search_results = Search::ProjectContext.new(@project, current_user, params).execute | 8 | + @search_results = Search::ProjectService.new(@project, current_user, params).execute |
9 | else | 9 | else |
10 | - @search_results = Search::GlobalContext.new(current_user, params).execute | 10 | + @search_results = Search::GlobalService.new(current_user, params).execute |
11 | end | 11 | end |
12 | end | 12 | end |
13 | end | 13 | end |
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +class BaseService | ||
2 | + attr_accessor :project, :current_user, :params | ||
3 | + | ||
4 | + def initialize(project, user, params) | ||
5 | + @project, @current_user, @params = project, user, params.dup | ||
6 | + end | ||
7 | + | ||
8 | + def abilities | ||
9 | + @abilities ||= begin | ||
10 | + abilities = Six.new | ||
11 | + abilities << Ability | ||
12 | + abilities | ||
13 | + end | ||
14 | + end | ||
15 | + | ||
16 | + def can?(object, action, subject) | ||
17 | + abilities.allowed?(object, action, subject) | ||
18 | + end | ||
19 | +end |
@@ -0,0 +1,31 @@ | @@ -0,0 +1,31 @@ | ||
1 | +module Files | ||
2 | + class BaseService < ::BaseService | ||
3 | + attr_reader :ref, :path | ||
4 | + | ||
5 | + def initialize(project, user, params, ref, path = nil) | ||
6 | + @project, @current_user, @params = project, user, params.dup | ||
7 | + @ref = ref | ||
8 | + @path = path | ||
9 | + end | ||
10 | + | ||
11 | + private | ||
12 | + | ||
13 | + def error(message) | ||
14 | + { | ||
15 | + error: message, | ||
16 | + status: :error | ||
17 | + } | ||
18 | + end | ||
19 | + | ||
20 | + def success | ||
21 | + { | ||
22 | + error: '', | ||
23 | + status: :success | ||
24 | + } | ||
25 | + end | ||
26 | + | ||
27 | + def repository | ||
28 | + project.repository | ||
29 | + end | ||
30 | + end | ||
31 | +end |
@@ -0,0 +1,47 @@ | @@ -0,0 +1,47 @@ | ||
1 | +require_relative "base_service" | ||
2 | + | ||
3 | +module Files | ||
4 | + class CreateService < BaseService | ||
5 | + def execute | ||
6 | + allowed = if project.protected_branch?(ref) | ||
7 | + can?(current_user, :push_code_to_protected_branches, project) | ||
8 | + else | ||
9 | + can?(current_user, :push_code, project) | ||
10 | + end | ||
11 | + | ||
12 | + unless allowed | ||
13 | + return error("You are not allowed to create file in this branch") | ||
14 | + end | ||
15 | + | ||
16 | + unless repository.branch_names.include?(ref) | ||
17 | + return error("You can only create files if you are on top of a branch") | ||
18 | + end | ||
19 | + | ||
20 | + file_name = File.basename(path) | ||
21 | + file_path = path | ||
22 | + | ||
23 | + unless file_name =~ Gitlab::Regex.path_regex | ||
24 | + return error("Your changes could not be committed, because file name contains not allowed characters") | ||
25 | + end | ||
26 | + | ||
27 | + blob = repository.blob_at(ref, file_path) | ||
28 | + | ||
29 | + if blob | ||
30 | + return error("Your changes could not be committed, because file with such name exists") | ||
31 | + end | ||
32 | + | ||
33 | + new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, file_path) | ||
34 | + created_successfully = new_file_action.commit!( | ||
35 | + params[:content], | ||
36 | + params[:commit_message], | ||
37 | + params[:encoding] | ||
38 | + ) | ||
39 | + | ||
40 | + if created_successfully | ||
41 | + success | ||
42 | + else | ||
43 | + error("Your changes could not be committed, because the file has been changed") | ||
44 | + end | ||
45 | + end | ||
46 | + end | ||
47 | +end |
@@ -0,0 +1,40 @@ | @@ -0,0 +1,40 @@ | ||
1 | +require_relative "base_service" | ||
2 | + | ||
3 | +module Files | ||
4 | + class DeleteService < BaseService | ||
5 | + def execute | ||
6 | + allowed = if project.protected_branch?(ref) | ||
7 | + can?(current_user, :push_code_to_protected_branches, project) | ||
8 | + else | ||
9 | + can?(current_user, :push_code, project) | ||
10 | + end | ||
11 | + | ||
12 | + unless allowed | ||
13 | + return error("You are not allowed to push into this branch") | ||
14 | + end | ||
15 | + | ||
16 | + unless repository.branch_names.include?(ref) | ||
17 | + return error("You can only create files if you are on top of a branch") | ||
18 | + end | ||
19 | + | ||
20 | + blob = repository.blob_at(ref, path) | ||
21 | + | ||
22 | + unless blob | ||
23 | + return error("You can only edit text files") | ||
24 | + end | ||
25 | + | ||
26 | + delete_file_action = Gitlab::Satellite::DeleteFileAction.new(current_user, project, ref, path) | ||
27 | + | ||
28 | + deleted_successfully = delete_file_action.commit!( | ||
29 | + nil, | ||
30 | + params[:commit_message] | ||
31 | + ) | ||
32 | + | ||
33 | + if deleted_successfully | ||
34 | + success | ||
35 | + else | ||
36 | + error("Your changes could not be committed, because the file has been changed") | ||
37 | + end | ||
38 | + end | ||
39 | + end | ||
40 | +end |
@@ -0,0 +1,40 @@ | @@ -0,0 +1,40 @@ | ||
1 | +require_relative "base_service" | ||
2 | + | ||
3 | +module Files | ||
4 | + class UpdateService < BaseService | ||
5 | + def execute | ||
6 | + allowed = if project.protected_branch?(ref) | ||
7 | + can?(current_user, :push_code_to_protected_branches, project) | ||
8 | + else | ||
9 | + can?(current_user, :push_code, project) | ||
10 | + end | ||
11 | + | ||
12 | + unless allowed | ||
13 | + return error("You are not allowed to push into this branch") | ||
14 | + end | ||
15 | + | ||
16 | + unless repository.branch_names.include?(ref) | ||
17 | + return error("You can only create files if you are on top of a branch") | ||
18 | + end | ||
19 | + | ||
20 | + blob = repository.blob_at(ref, path) | ||
21 | + | ||
22 | + unless blob | ||
23 | + return error("You can only edit text files") | ||
24 | + end | ||
25 | + | ||
26 | + edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path) | ||
27 | + created_successfully = edit_file_action.commit!( | ||
28 | + params[:content], | ||
29 | + params[:commit_message], | ||
30 | + params[:encoding] | ||
31 | + ) | ||
32 | + | ||
33 | + if created_successfully | ||
34 | + success | ||
35 | + else | ||
36 | + error("Your changes could not be committed, because the file has been changed") | ||
37 | + end | ||
38 | + end | ||
39 | + end | ||
40 | +end |
@@ -0,0 +1,39 @@ | @@ -0,0 +1,39 @@ | ||
1 | +module Issues | ||
2 | + class BulkUpdateService < BaseService | ||
3 | + def execute | ||
4 | + update_data = params[:update] | ||
5 | + | ||
6 | + issues_ids = update_data[:issues_ids].split(",") | ||
7 | + milestone_id = update_data[:milestone_id] | ||
8 | + assignee_id = update_data[:assignee_id] | ||
9 | + status = update_data[:status] | ||
10 | + | ||
11 | + new_state = nil | ||
12 | + | ||
13 | + if status.present? | ||
14 | + if status == 'closed' | ||
15 | + new_state = :close | ||
16 | + else | ||
17 | + new_state = :reopen | ||
18 | + end | ||
19 | + end | ||
20 | + | ||
21 | + opts = {} | ||
22 | + opts[:milestone_id] = milestone_id if milestone_id.present? | ||
23 | + opts[:assignee_id] = assignee_id if assignee_id.present? | ||
24 | + | ||
25 | + issues = Issue.where(id: issues_ids) | ||
26 | + issues = issues.select { |issue| can?(current_user, :modify_issue, issue) } | ||
27 | + | ||
28 | + issues.each do |issue| | ||
29 | + issue.update_attributes(opts) | ||
30 | + issue.send new_state if new_state | ||
31 | + end | ||
32 | + | ||
33 | + { | ||
34 | + count: issues.count, | ||
35 | + success: !issues.count.zero? | ||
36 | + } | ||
37 | + end | ||
38 | + end | ||
39 | +end |
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +module Notes | ||
2 | + class LoadService < BaseService | ||
3 | + def execute | ||
4 | + target_type = params[:target_type] | ||
5 | + target_id = params[:target_id] | ||
6 | + | ||
7 | + | ||
8 | + @notes = case target_type | ||
9 | + when "commit" | ||
10 | + project.notes.for_commit_id(target_id).not_inline.fresh | ||
11 | + when "issue" | ||
12 | + project.issues.find(target_id).notes.inc_author.fresh | ||
13 | + when "merge_request" | ||
14 | + project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh | ||
15 | + when "snippet" | ||
16 | + project.snippets.find(target_id).notes.fresh | ||
17 | + end | ||
18 | + end | ||
19 | + end | ||
20 | +end |
@@ -0,0 +1,80 @@ | @@ -0,0 +1,80 @@ | ||
1 | +module Projects | ||
2 | + class CreateService < BaseService | ||
3 | + def initialize(user, params) | ||
4 | + @current_user, @params = user, params.dup | ||
5 | + end | ||
6 | + | ||
7 | + def execute | ||
8 | + # get namespace id | ||
9 | + namespace_id = params.delete(:namespace_id) | ||
10 | + | ||
11 | + # check that user is allowed to set specified visibility_level | ||
12 | + unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) | ||
13 | + params.delete(:visibility_level) | ||
14 | + end | ||
15 | + | ||
16 | + # Load default feature settings | ||
17 | + default_features = Gitlab.config.gitlab.default_projects_features | ||
18 | + | ||
19 | + default_opts = { | ||
20 | + issues_enabled: default_features.issues, | ||
21 | + wiki_enabled: default_features.wiki, | ||
22 | + wall_enabled: default_features.wall, | ||
23 | + snippets_enabled: default_features.snippets, | ||
24 | + merge_requests_enabled: default_features.merge_requests, | ||
25 | + visibility_level: default_features.visibility_level | ||
26 | + }.stringify_keys | ||
27 | + | ||
28 | + @project = Project.new(default_opts.merge(params)) | ||
29 | + | ||
30 | + # Parametrize path for project | ||
31 | + # | ||
32 | + # Ex. | ||
33 | + # 'GitLab HQ'.parameterize => "gitlab-hq" | ||
34 | + # | ||
35 | + @project.path = @project.name.dup.parameterize unless @project.path.present? | ||
36 | + | ||
37 | + | ||
38 | + if namespace_id | ||
39 | + # Find matching namespace and check if it allowed | ||
40 | + # for current user if namespace_id passed. | ||
41 | + if allowed_namespace?(current_user, namespace_id) | ||
42 | + @project.namespace_id = namespace_id | ||
43 | + else | ||
44 | + deny_namespace | ||
45 | + return @project | ||
46 | + end | ||
47 | + else | ||
48 | + # Set current user namespace if namespace_id is nil | ||
49 | + @project.namespace_id = current_user.namespace_id | ||
50 | + end | ||
51 | + | ||
52 | + @project.creator = current_user | ||
53 | + | ||
54 | + if @project.save | ||
55 | + unless @project.group | ||
56 | + @project.users_projects.create( | ||
57 | + project_access: UsersProject::MASTER, | ||
58 | + user: current_user | ||
59 | + ) | ||
60 | + end | ||
61 | + end | ||
62 | + | ||
63 | + @project | ||
64 | + rescue => ex | ||
65 | + @project.errors.add(:base, "Can't save project. Please try again later") | ||
66 | + @project | ||
67 | + end | ||
68 | + | ||
69 | + protected | ||
70 | + | ||
71 | + def deny_namespace | ||
72 | + @project.errors.add(:namespace, "is not valid") | ||
73 | + end | ||
74 | + | ||
75 | + def allowed_namespace?(user, namespace_id) | ||
76 | + namespace = Namespace.find_by_id(namespace_id) | ||
77 | + current_user.can?(:manage_namespace, namespace) | ||
78 | + end | ||
79 | + end | ||
80 | +end |
@@ -0,0 +1,44 @@ | @@ -0,0 +1,44 @@ | ||
1 | +module Projects | ||
2 | + class ForkService < BaseService | ||
3 | + include Gitlab::ShellAdapter | ||
4 | + | ||
5 | + def initialize(project, user) | ||
6 | + @from_project, @current_user = project, user | ||
7 | + end | ||
8 | + | ||
9 | + def execute | ||
10 | + project = @from_project.dup | ||
11 | + project.name = @from_project.name | ||
12 | + project.path = @from_project.path | ||
13 | + project.namespace = current_user.namespace | ||
14 | + project.creator = current_user | ||
15 | + | ||
16 | + # If the project cannot save, we do not want to trigger the project destroy | ||
17 | + # as this can have the side effect of deleting a repo attached to an existing | ||
18 | + # project with the same name and namespace | ||
19 | + if project.valid? | ||
20 | + begin | ||
21 | + Project.transaction do | ||
22 | + #First save the DB entries as they can be rolled back if the repo fork fails | ||
23 | + project.build_forked_project_link(forked_to_project_id: project.id, forked_from_project_id: @from_project.id) | ||
24 | + if project.save | ||
25 | + project.users_projects.create(project_access: UsersProject::MASTER, user: current_user) | ||
26 | + end | ||
27 | + #Now fork the repo | ||
28 | + unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path) | ||
29 | + raise "forking failed in gitlab-shell" | ||
30 | + end | ||
31 | + project.ensure_satellite_exists | ||
32 | + end | ||
33 | + rescue => ex | ||
34 | + project.errors.add(:base, "Fork transaction failed.") | ||
35 | + project.destroy | ||
36 | + end | ||
37 | + else | ||
38 | + project.errors.add(:base, "Invalid fork destination") | ||
39 | + end | ||
40 | + project | ||
41 | + | ||
42 | + end | ||
43 | + end | ||
44 | +end |
@@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
1 | +module Projects | ||
2 | + class TransferService < BaseService | ||
3 | + def execute(role = :default) | ||
4 | + namespace_id = params[:project].delete(:namespace_id) | ||
5 | + allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin | ||
6 | + | ||
7 | + if allowed_transfer && namespace_id.present? | ||
8 | + if namespace_id.to_i != project.namespace_id | ||
9 | + # Transfer to someone namespace | ||
10 | + namespace = Namespace.find(namespace_id) | ||
11 | + project.transfer(namespace) | ||
12 | + end | ||
13 | + end | ||
14 | + | ||
15 | + rescue ProjectTransferService::TransferError => ex | ||
16 | + project.reload | ||
17 | + project.errors.add(:namespace_id, ex.message) | ||
18 | + false | ||
19 | + end | ||
20 | + end | ||
21 | +end | ||
22 | + |
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +module Projects | ||
2 | + class UpdateService < BaseService | ||
3 | + def execute(role = :default) | ||
4 | + params[:project].delete(:namespace_id) | ||
5 | + # check that user is allowed to set specified visibility_level | ||
6 | + unless can?(current_user, :change_visibility_level, project) && Gitlab::VisibilityLevel.allowed_for?(current_user, params[:project][:visibility_level]) | ||
7 | + params[:project].delete(:visibility_level) | ||
8 | + end | ||
9 | + | ||
10 | + new_branch = params[:project].delete(:default_branch) | ||
11 | + | ||
12 | + if project.repository.exists? && new_branch && new_branch != project.default_branch | ||
13 | + project.change_head(new_branch) | ||
14 | + end | ||
15 | + | ||
16 | + project.update_attributes(params[:project], as: role) | ||
17 | + end | ||
18 | + end | ||
19 | +end |
@@ -0,0 +1,40 @@ | @@ -0,0 +1,40 @@ | ||
1 | +module Search | ||
2 | + class GlobalService | ||
3 | + attr_accessor :current_user, :params | ||
4 | + | ||
5 | + def initialize(user, params) | ||
6 | + @current_user, @params = user, params.dup | ||
7 | + end | ||
8 | + | ||
9 | + def execute | ||
10 | + query = params[:search] | ||
11 | + query = Shellwords.shellescape(query) if query.present? | ||
12 | + return result unless query.present? | ||
13 | + | ||
14 | + authorized_projects_ids = [] | ||
15 | + authorized_projects_ids += current_user.authorized_projects.pluck(:id) if current_user | ||
16 | + authorized_projects_ids += Project.public_or_internal_only(current_user).pluck(:id) | ||
17 | + | ||
18 | + group = Group.find_by_id(params[:group_id]) if params[:group_id].present? | ||
19 | + projects = Project.where(id: authorized_projects_ids) | ||
20 | + projects = projects.where(namespace_id: group.id) if group | ||
21 | + projects = projects.search(query) | ||
22 | + project_ids = projects.pluck(:id) | ||
23 | + | ||
24 | + result[:projects] = projects.limit(20) | ||
25 | + result[:merge_requests] = MergeRequest.in_projects(project_ids).search(query).order('updated_at DESC').limit(20) | ||
26 | + result[:issues] = Issue.where(project_id: project_ids).search(query).order('updated_at DESC').limit(20) | ||
27 | + result[:total_results] = %w(projects issues merge_requests).sum { |items| result[items.to_sym].size } | ||
28 | + result | ||
29 | + end | ||
30 | + | ||
31 | + def result | ||
32 | + @result ||= { | ||
33 | + projects: [], | ||
34 | + merge_requests: [], | ||
35 | + issues: [], | ||
36 | + total_results: 0, | ||
37 | + } | ||
38 | + end | ||
39 | + end | ||
40 | +end |
@@ -0,0 +1,37 @@ | @@ -0,0 +1,37 @@ | ||
1 | +module Search | ||
2 | + class ProjectService | ||
3 | + attr_accessor :project, :current_user, :params | ||
4 | + | ||
5 | + def initialize(project, user, params) | ||
6 | + @project, @current_user, @params = project, user, params.dup | ||
7 | + end | ||
8 | + | ||
9 | + def execute | ||
10 | + query = params[:search] | ||
11 | + query = Shellwords.shellescape(query) if query.present? | ||
12 | + return result unless query.present? | ||
13 | + | ||
14 | + if params[:search_code].present? | ||
15 | + blobs = project.repository.search_files(query, params[:repository_ref]) unless project.empty_repo? | ||
16 | + blobs = Kaminari.paginate_array(blobs).page(params[:page]).per(20) | ||
17 | + result[:blobs] = blobs | ||
18 | + result[:total_results] = blobs.total_count | ||
19 | + else | ||
20 | + result[:merge_requests] = project.merge_requests.search(query).order('updated_at DESC').limit(20) | ||
21 | + result[:issues] = project.issues.search(query).order('updated_at DESC').limit(20) | ||
22 | + result[:total_results] = %w(issues merge_requests).sum { |items| result[items.to_sym].size } | ||
23 | + end | ||
24 | + | ||
25 | + result | ||
26 | + end | ||
27 | + | ||
28 | + def result | ||
29 | + @result ||= { | ||
30 | + merge_requests: [], | ||
31 | + issues: [], | ||
32 | + blobs: [], | ||
33 | + total_results: 0, | ||
34 | + } | ||
35 | + end | ||
36 | + end | ||
37 | +end |
lib/api/files.rb
@@ -21,7 +21,7 @@ module API | @@ -21,7 +21,7 @@ module API | ||
21 | attrs = attributes_for_keys [:file_path, :branch_name, :content, :commit_message, :encoding] | 21 | attrs = attributes_for_keys [:file_path, :branch_name, :content, :commit_message, :encoding] |
22 | branch_name = attrs.delete(:branch_name) | 22 | branch_name = attrs.delete(:branch_name) |
23 | file_path = attrs.delete(:file_path) | 23 | file_path = attrs.delete(:file_path) |
24 | - result = ::Files::CreateContext.new(user_project, current_user, attrs, branch_name, file_path).execute | 24 | + result = ::Files::CreateService.new(user_project, current_user, attrs, branch_name, file_path).execute |
25 | 25 | ||
26 | if result[:status] == :success | 26 | if result[:status] == :success |
27 | status(201) | 27 | status(201) |
@@ -51,7 +51,7 @@ module API | @@ -51,7 +51,7 @@ module API | ||
51 | attrs = attributes_for_keys [:file_path, :branch_name, :content, :commit_message, :encoding] | 51 | attrs = attributes_for_keys [:file_path, :branch_name, :content, :commit_message, :encoding] |
52 | branch_name = attrs.delete(:branch_name) | 52 | branch_name = attrs.delete(:branch_name) |
53 | file_path = attrs.delete(:file_path) | 53 | file_path = attrs.delete(:file_path) |
54 | - result = ::Files::UpdateContext.new(user_project, current_user, attrs, branch_name, file_path).execute | 54 | + result = ::Files::UpdateService.new(user_project, current_user, attrs, branch_name, file_path).execute |
55 | 55 | ||
56 | if result[:status] == :success | 56 | if result[:status] == :success |
57 | status(200) | 57 | status(200) |
@@ -81,7 +81,7 @@ module API | @@ -81,7 +81,7 @@ module API | ||
81 | attrs = attributes_for_keys [:file_path, :branch_name, :commit_message] | 81 | attrs = attributes_for_keys [:file_path, :branch_name, :commit_message] |
82 | branch_name = attrs.delete(:branch_name) | 82 | branch_name = attrs.delete(:branch_name) |
83 | file_path = attrs.delete(:file_path) | 83 | file_path = attrs.delete(:file_path) |
84 | - result = ::Files::DeleteContext.new(user_project, current_user, attrs, branch_name, file_path).execute | 84 | + result = ::Files::DeleteService.new(user_project, current_user, attrs, branch_name, file_path).execute |
85 | 85 | ||
86 | if result[:status] == :success | 86 | if result[:status] == :success |
87 | status(200) | 87 | status(200) |
lib/api/projects.rb
@@ -102,7 +102,7 @@ module API | @@ -102,7 +102,7 @@ module API | ||
102 | :visibility_level, | 102 | :visibility_level, |
103 | :import_url] | 103 | :import_url] |
104 | attrs = map_public_to_visibility_level(attrs) | 104 | attrs = map_public_to_visibility_level(attrs) |
105 | - @project = ::Projects::CreateContext.new(current_user, attrs).execute | 105 | + @project = ::Projects::CreateService.new(current_user, attrs).execute |
106 | if @project.saved? | 106 | if @project.saved? |
107 | present @project, with: Entities::Project | 107 | present @project, with: Entities::Project |
108 | else | 108 | else |
@@ -143,7 +143,7 @@ module API | @@ -143,7 +143,7 @@ module API | ||
143 | :public, | 143 | :public, |
144 | :visibility_level] | 144 | :visibility_level] |
145 | attrs = map_public_to_visibility_level(attrs) | 145 | attrs = map_public_to_visibility_level(attrs) |
146 | - @project = ::Projects::CreateContext.new(user, attrs).execute | 146 | + @project = ::Projects::CreateService.new(user, attrs).execute |
147 | if @project.saved? | 147 | if @project.saved? |
148 | present @project, with: Entities::Project | 148 | present @project, with: Entities::Project |
149 | else | 149 | else |
lib/tasks/gitlab/import.rake
@@ -66,7 +66,7 @@ namespace :gitlab do | @@ -66,7 +66,7 @@ namespace :gitlab do | ||
66 | project_params[:namespace_id] = group.id | 66 | project_params[:namespace_id] = group.id |
67 | end | 67 | end |
68 | 68 | ||
69 | - project = Projects::CreateContext.new(user, project_params).execute | 69 | + project = Projects::CreateService.new(user, project_params).execute |
70 | 70 | ||
71 | if project.valid? | 71 | if project.valid? |
72 | puts " * Created #{project.name} (#{repo_path})".green | 72 | puts " * Created #{project.name} (#{repo_path})".green |
spec/contexts/fork_context_spec.rb
@@ -1,57 +0,0 @@ | @@ -1,57 +0,0 @@ | ||
1 | -require 'spec_helper' | ||
2 | - | ||
3 | -describe Projects::ForkContext do | ||
4 | - describe :fork_by_user do | ||
5 | - before do | ||
6 | - @from_namespace = create(:namespace) | ||
7 | - @from_user = create(:user, namespace: @from_namespace ) | ||
8 | - @from_project = create(:project, creator_id: @from_user.id, namespace: @from_namespace) | ||
9 | - @to_namespace = create(:namespace) | ||
10 | - @to_user = create(:user, namespace: @to_namespace) | ||
11 | - end | ||
12 | - | ||
13 | - context 'fork project' do | ||
14 | - | ||
15 | - it "successfully creates project in the user namespace" do | ||
16 | - @to_project = fork_project(@from_project, @to_user) | ||
17 | - | ||
18 | - @to_project.owner.should == @to_user | ||
19 | - @to_project.namespace.should == @to_user.namespace | ||
20 | - end | ||
21 | - end | ||
22 | - | ||
23 | - context 'fork project failure' do | ||
24 | - | ||
25 | - it "fails due to transaction failure" do | ||
26 | - # make the mock gitlab-shell fail | ||
27 | - @to_project = fork_project(@from_project, @to_user, false) | ||
28 | - | ||
29 | - @to_project.errors.should_not be_empty | ||
30 | - @to_project.errors[:base].should include("Fork transaction failed.") | ||
31 | - end | ||
32 | - | ||
33 | - end | ||
34 | - | ||
35 | - context 'project already exists' do | ||
36 | - | ||
37 | - it "should fail due to validation, not transaction failure" do | ||
38 | - @existing_project = create(:project, creator_id: @to_user.id, name: @from_project.name, namespace: @to_namespace) | ||
39 | - @to_project = fork_project(@from_project, @to_user) | ||
40 | - | ||
41 | - @existing_project.persisted?.should be_true | ||
42 | - @to_project.errors[:base].should include("Invalid fork destination") | ||
43 | - @to_project.errors[:base].should_not include("Fork transaction failed.") | ||
44 | - end | ||
45 | - | ||
46 | - end | ||
47 | - end | ||
48 | - | ||
49 | - def fork_project(from_project, user, fork_success = true) | ||
50 | - context = Projects::ForkContext.new(from_project, user) | ||
51 | - shell = double("gitlab_shell") | ||
52 | - shell.stub(fork_repository: fork_success) | ||
53 | - context.stub(gitlab_shell: shell) | ||
54 | - context.execute | ||
55 | - end | ||
56 | - | ||
57 | -end |
spec/contexts/issues/bulk_update_context_spec.rb
@@ -1,113 +0,0 @@ | @@ -1,113 +0,0 @@ | ||
1 | -require 'spec_helper' | ||
2 | - | ||
3 | -describe Issues::BulkUpdateContext do | ||
4 | - before(:each) { ActiveRecord::Base.observers.enable(:user_observer) } | ||
5 | - after(:each) { ActiveRecord::Base.observers.disable(:user_observer) } | ||
6 | - | ||
7 | - let(:issue) { | ||
8 | - create(:issue, project: @project) | ||
9 | - } | ||
10 | - | ||
11 | - before do | ||
12 | - @user = create :user | ||
13 | - opts = { | ||
14 | - name: "GitLab", | ||
15 | - namespace: @user.namespace | ||
16 | - } | ||
17 | - @project = Projects::CreateContext.new(@user, opts).execute | ||
18 | - end | ||
19 | - | ||
20 | - describe :close_issue do | ||
21 | - | ||
22 | - before do | ||
23 | - @issues = 5.times.collect do | ||
24 | - create(:issue, project: @project) | ||
25 | - end | ||
26 | - @params = { | ||
27 | - update: { | ||
28 | - status: 'closed', | ||
29 | - issues_ids: @issues.map(&:id) | ||
30 | - } | ||
31 | - } | ||
32 | - end | ||
33 | - | ||
34 | - it { | ||
35 | - result = Issues::BulkUpdateContext.new(@project, @user, @params).execute | ||
36 | - result[:success].should be_true | ||
37 | - result[:count].should == @issues.count | ||
38 | - | ||
39 | - @project.issues.opened.should be_empty | ||
40 | - @project.issues.closed.should_not be_empty | ||
41 | - } | ||
42 | - | ||
43 | - end | ||
44 | - | ||
45 | - describe :reopen_issues do | ||
46 | - | ||
47 | - before do | ||
48 | - @issues = 5.times.collect do | ||
49 | - create(:closed_issue, project: @project) | ||
50 | - end | ||
51 | - @params = { | ||
52 | - update: { | ||
53 | - status: 'reopen', | ||
54 | - issues_ids: @issues.map(&:id) | ||
55 | - } | ||
56 | - } | ||
57 | - end | ||
58 | - | ||
59 | - it { | ||
60 | - result = Issues::BulkUpdateContext.new(@project, @user, @params).execute | ||
61 | - result[:success].should be_true | ||
62 | - result[:count].should == @issues.count | ||
63 | - | ||
64 | - @project.issues.closed.should be_empty | ||
65 | - @project.issues.opened.should_not be_empty | ||
66 | - } | ||
67 | - | ||
68 | - end | ||
69 | - | ||
70 | - describe :update_assignee do | ||
71 | - | ||
72 | - before do | ||
73 | - @new_assignee = create :user | ||
74 | - @params = { | ||
75 | - update: { | ||
76 | - issues_ids: [issue.id], | ||
77 | - assignee_id: @new_assignee.id | ||
78 | - } | ||
79 | - } | ||
80 | - end | ||
81 | - | ||
82 | - it { | ||
83 | - result = Issues::BulkUpdateContext.new(@project, @user, @params).execute | ||
84 | - result[:success].should be_true | ||
85 | - result[:count].should == 1 | ||
86 | - | ||
87 | - @project.issues.first.assignee.should == @new_assignee | ||
88 | - } | ||
89 | - | ||
90 | - end | ||
91 | - | ||
92 | - describe :update_milestone do | ||
93 | - | ||
94 | - before do | ||
95 | - @milestone = create :milestone | ||
96 | - @params = { | ||
97 | - update: { | ||
98 | - issues_ids: [issue.id], | ||
99 | - milestone_id: @milestone.id | ||
100 | - } | ||
101 | - } | ||
102 | - end | ||
103 | - | ||
104 | - it { | ||
105 | - result = Issues::BulkUpdateContext.new(@project, @user, @params).execute | ||
106 | - result[:success].should be_true | ||
107 | - result[:count].should == 1 | ||
108 | - | ||
109 | - @project.issues.first.milestone.should == @milestone | ||
110 | - } | ||
111 | - end | ||
112 | - | ||
113 | -end |
spec/contexts/projects_create_context_spec.rb
@@ -1,142 +0,0 @@ | @@ -1,142 +0,0 @@ | ||
1 | -require 'spec_helper' | ||
2 | - | ||
3 | -describe Projects::CreateContext do | ||
4 | - before(:each) { ActiveRecord::Base.observers.enable(:user_observer) } | ||
5 | - after(:each) { ActiveRecord::Base.observers.disable(:user_observer) } | ||
6 | - | ||
7 | - describe :create_by_user do | ||
8 | - before do | ||
9 | - @user = create :user | ||
10 | - @admin = create :user, admin: true | ||
11 | - @opts = { | ||
12 | - name: "GitLab", | ||
13 | - namespace: @user.namespace | ||
14 | - } | ||
15 | - end | ||
16 | - | ||
17 | - context 'user namespace' do | ||
18 | - before do | ||
19 | - @project = create_project(@user, @opts) | ||
20 | - end | ||
21 | - | ||
22 | - it { @project.should be_valid } | ||
23 | - it { @project.owner.should == @user } | ||
24 | - it { @project.namespace.should == @user.namespace } | ||
25 | - end | ||
26 | - | ||
27 | - context 'group namespace' do | ||
28 | - before do | ||
29 | - @group = create :group | ||
30 | - @group.add_owner(@user) | ||
31 | - | ||
32 | - @opts.merge!(namespace_id: @group.id) | ||
33 | - @project = create_project(@user, @opts) | ||
34 | - end | ||
35 | - | ||
36 | - it { @project.should be_valid } | ||
37 | - it { @project.owner.should == @group } | ||
38 | - it { @project.namespace.should == @group } | ||
39 | - end | ||
40 | - | ||
41 | - context 'respect configured visibility setting' do | ||
42 | - before(:each) do | ||
43 | - @settings = double("settings") | ||
44 | - @settings.stub(:issues) { true } | ||
45 | - @settings.stub(:merge_requests) { true } | ||
46 | - @settings.stub(:wiki) { true } | ||
47 | - @settings.stub(:wall) { true } | ||
48 | - @settings.stub(:snippets) { true } | ||
49 | - stub_const("Settings", Class.new) | ||
50 | - @restrictions = double("restrictions") | ||
51 | - @restrictions.stub(:restricted_visibility_levels) { [] } | ||
52 | - Settings.stub_chain(:gitlab).and_return(@restrictions) | ||
53 | - Settings.stub_chain(:gitlab, :default_projects_features).and_return(@settings) | ||
54 | - end | ||
55 | - | ||
56 | - context 'should be public when setting is public' do | ||
57 | - before do | ||
58 | - @settings.stub(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC } | ||
59 | - @project = create_project(@user, @opts) | ||
60 | - end | ||
61 | - | ||
62 | - it { @project.public?.should be_true } | ||
63 | - end | ||
64 | - | ||
65 | - context 'should be private when setting is private' do | ||
66 | - before do | ||
67 | - @settings.stub(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE } | ||
68 | - @project = create_project(@user, @opts) | ||
69 | - end | ||
70 | - | ||
71 | - it { @project.private?.should be_true } | ||
72 | - end | ||
73 | - | ||
74 | - context 'should be internal when setting is internal' do | ||
75 | - before do | ||
76 | - @settings.stub(:visibility_level) { Gitlab::VisibilityLevel::INTERNAL } | ||
77 | - @project = create_project(@user, @opts) | ||
78 | - end | ||
79 | - | ||
80 | - it { @project.internal?.should be_true } | ||
81 | - end | ||
82 | - end | ||
83 | - | ||
84 | - context 'respect configured visibility restrictions setting' do | ||
85 | - before(:each) do | ||
86 | - @settings = double("settings") | ||
87 | - @settings.stub(:issues) { true } | ||
88 | - @settings.stub(:merge_requests) { true } | ||
89 | - @settings.stub(:wiki) { true } | ||
90 | - @settings.stub(:wall) { true } | ||
91 | - @settings.stub(:snippets) { true } | ||
92 | - @settings.stub(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE } | ||
93 | - stub_const("Settings", Class.new) | ||
94 | - @restrictions = double("restrictions") | ||
95 | - @restrictions.stub(:restricted_visibility_levels) { [ Gitlab::VisibilityLevel::PUBLIC ] } | ||
96 | - Settings.stub_chain(:gitlab).and_return(@restrictions) | ||
97 | - Settings.stub_chain(:gitlab, :default_projects_features).and_return(@settings) | ||
98 | - end | ||
99 | - | ||
100 | - context 'should be private when option is public' do | ||
101 | - before do | ||
102 | - @opts.merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) | ||
103 | - @project = create_project(@user, @opts) | ||
104 | - end | ||
105 | - | ||
106 | - it { @project.private?.should be_true } | ||
107 | - end | ||
108 | - | ||
109 | - context 'should be public when option is public for admin' do | ||
110 | - before do | ||
111 | - @opts.merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) | ||
112 | - @project = create_project(@admin, @opts) | ||
113 | - end | ||
114 | - | ||
115 | - it { @project.public?.should be_true } | ||
116 | - end | ||
117 | - | ||
118 | - context 'should be private when option is private' do | ||
119 | - before do | ||
120 | - @opts.merge!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) | ||
121 | - @project = create_project(@user, @opts) | ||
122 | - end | ||
123 | - | ||
124 | - it { @project.private?.should be_true } | ||
125 | - end | ||
126 | - | ||
127 | - context 'should be internal when option is internal' do | ||
128 | - before do | ||
129 | - @opts.merge!(visibility_level: Gitlab::VisibilityLevel::INTERNAL) | ||
130 | - @project = create_project(@user, @opts) | ||
131 | - end | ||
132 | - | ||
133 | - it { @project.internal?.should be_true } | ||
134 | - end | ||
135 | - end | ||
136 | - end | ||
137 | - | ||
138 | - def create_project(user, opts) | ||
139 | - Projects::CreateContext.new(user, opts).execute | ||
140 | - end | ||
141 | -end | ||
142 | - |
spec/contexts/projects_update_context_spec.rb
@@ -1,111 +0,0 @@ | @@ -1,111 +0,0 @@ | ||
1 | -require 'spec_helper' | ||
2 | - | ||
3 | -describe Projects::UpdateContext do | ||
4 | - before(:each) { ActiveRecord::Base.observers.enable(:user_observer) } | ||
5 | - after(:each) { ActiveRecord::Base.observers.disable(:user_observer) } | ||
6 | - | ||
7 | - describe :update_by_user do | ||
8 | - before do | ||
9 | - @user = create :user | ||
10 | - @admin = create :user, admin: true | ||
11 | - @project = create :project, creator_id: @user.id, namespace: @user.namespace | ||
12 | - @opts = { project: {} } | ||
13 | - end | ||
14 | - | ||
15 | - context 'should be private when updated to private' do | ||
16 | - before do | ||
17 | - @created_private = @project.private? | ||
18 | - | ||
19 | - @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) | ||
20 | - update_project(@project, @user, @opts) | ||
21 | - end | ||
22 | - | ||
23 | - it { @created_private.should be_true } | ||
24 | - it { @project.private?.should be_true } | ||
25 | - end | ||
26 | - | ||
27 | - context 'should be internal when updated to internal' do | ||
28 | - before do | ||
29 | - @created_private = @project.private? | ||
30 | - | ||
31 | - @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::INTERNAL) | ||
32 | - update_project(@project, @user, @opts) | ||
33 | - end | ||
34 | - | ||
35 | - it { @created_private.should be_true } | ||
36 | - it { @project.internal?.should be_true } | ||
37 | - end | ||
38 | - | ||
39 | - context 'should be public when updated to public' do | ||
40 | - before do | ||
41 | - @created_private = @project.private? | ||
42 | - | ||
43 | - @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) | ||
44 | - update_project(@project, @user, @opts) | ||
45 | - end | ||
46 | - | ||
47 | - it { @created_private.should be_true } | ||
48 | - it { @project.public?.should be_true } | ||
49 | - end | ||
50 | - | ||
51 | - context 'respect configured visibility restrictions setting' do | ||
52 | - before(:each) do | ||
53 | - @restrictions = double("restrictions") | ||
54 | - @restrictions.stub(:restricted_visibility_levels) { [ Gitlab::VisibilityLevel::PUBLIC ] } | ||
55 | - Settings.stub_chain(:gitlab).and_return(@restrictions) | ||
56 | - end | ||
57 | - | ||
58 | - context 'should be private when updated to private' do | ||
59 | - before do | ||
60 | - @created_private = @project.private? | ||
61 | - | ||
62 | - @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) | ||
63 | - update_project(@project, @user, @opts) | ||
64 | - end | ||
65 | - | ||
66 | - it { @created_private.should be_true } | ||
67 | - it { @project.private?.should be_true } | ||
68 | - end | ||
69 | - | ||
70 | - context 'should be internal when updated to internal' do | ||
71 | - before do | ||
72 | - @created_private = @project.private? | ||
73 | - | ||
74 | - @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::INTERNAL) | ||
75 | - update_project(@project, @user, @opts) | ||
76 | - end | ||
77 | - | ||
78 | - it { @created_private.should be_true } | ||
79 | - it { @project.internal?.should be_true } | ||
80 | - end | ||
81 | - | ||
82 | - context 'should be private when updated to public' do | ||
83 | - before do | ||
84 | - @created_private = @project.private? | ||
85 | - | ||
86 | - @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) | ||
87 | - update_project(@project, @user, @opts) | ||
88 | - end | ||
89 | - | ||
90 | - it { @created_private.should be_true } | ||
91 | - it { @project.private?.should be_true } | ||
92 | - end | ||
93 | - | ||
94 | - context 'should be public when updated to public by admin' do | ||
95 | - before do | ||
96 | - @created_private = @project.private? | ||
97 | - | ||
98 | - @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) | ||
99 | - update_project(@project, @admin, @opts) | ||
100 | - end | ||
101 | - | ||
102 | - it { @created_private.should be_true } | ||
103 | - it { @project.public?.should be_true } | ||
104 | - end | ||
105 | - end | ||
106 | - end | ||
107 | - | ||
108 | - def update_project(project, user, opts) | ||
109 | - Projects::UpdateContext.new(project, user, opts).execute | ||
110 | - end | ||
111 | -end | ||
112 | \ No newline at end of file | 0 | \ No newline at end of file |
spec/contexts/search_context_spec.rb
@@ -1,54 +0,0 @@ | @@ -1,54 +0,0 @@ | ||
1 | -require 'spec_helper' | ||
2 | - | ||
3 | -describe 'Search::GlobalContext' do | ||
4 | - let(:found_namespace) { create(:namespace, name: 'searchable namespace', path:'another_thing') } | ||
5 | - let(:user) { create(:user, namespace: found_namespace) } | ||
6 | - let!(:found_project) { create(:project, name: 'searchable_project', creator_id: user.id, namespace: found_namespace, visibility_level: Gitlab::VisibilityLevel::PRIVATE) } | ||
7 | - | ||
8 | - let(:unfound_namespace) { create(:namespace, name: 'unfound namespace', path: 'yet_something_else') } | ||
9 | - let!(:unfound_project) { create(:project, name: 'unfound_project', creator_id: user.id, namespace: unfound_namespace, visibility_level: Gitlab::VisibilityLevel::PRIVATE) } | ||
10 | - | ||
11 | - let(:internal_namespace) { create(:namespace, path: 'something_internal',name: 'searchable internal namespace') } | ||
12 | - let(:internal_user) { create(:user, namespace: internal_namespace) } | ||
13 | - let!(:internal_project) { create(:project, name: 'searchable_internal_project', creator_id: internal_user.id, namespace: internal_namespace, visibility_level: Gitlab::VisibilityLevel::INTERNAL) } | ||
14 | - | ||
15 | - let(:public_namespace) { create(:namespace, path: 'something_public',name: 'searchable public namespace') } | ||
16 | - let(:public_user) { create(:user, namespace: public_namespace) } | ||
17 | - let!(:public_project) { create(:project, name: 'searchable_public_project', creator_id: public_user.id, namespace: public_namespace, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } | ||
18 | - | ||
19 | - describe '#execute' do | ||
20 | - context 'unauthenticated' do | ||
21 | - it 'should return public projects only' do | ||
22 | - context = Search::GlobalContext.new(nil, search: "searchable") | ||
23 | - results = context.execute | ||
24 | - results[:projects].should have(1).items | ||
25 | - results[:projects].should include(public_project) | ||
26 | - end | ||
27 | - end | ||
28 | - | ||
29 | - context 'authenticated' do | ||
30 | - it 'should return public, internal and private projects' do | ||
31 | - context = Search::GlobalContext.new(user, search: "searchable") | ||
32 | - results = context.execute | ||
33 | - results[:projects].should have(3).items | ||
34 | - results[:projects].should include(public_project) | ||
35 | - results[:projects].should include(found_project) | ||
36 | - results[:projects].should include(internal_project) | ||
37 | - end | ||
38 | - | ||
39 | - it 'should return only public & internal projects' do | ||
40 | - context = Search::GlobalContext.new(internal_user, search: "searchable") | ||
41 | - results = context.execute | ||
42 | - results[:projects].should have(2).items | ||
43 | - results[:projects].should include(internal_project) | ||
44 | - results[:projects].should include(public_project) | ||
45 | - end | ||
46 | - | ||
47 | - it 'namespace name should be searchable' do | ||
48 | - context = Search::GlobalContext.new(user, search: "searchable namespace") | ||
49 | - results = context.execute | ||
50 | - results[:projects].should == [found_project] | ||
51 | - end | ||
52 | - end | ||
53 | - end | ||
54 | -end |
spec/models/forked_project_link_spec.rb
@@ -58,7 +58,7 @@ describe :forked_from_project do | @@ -58,7 +58,7 @@ describe :forked_from_project do | ||
58 | end | 58 | end |
59 | 59 | ||
60 | def fork_project(from_project, user) | 60 | def fork_project(from_project, user) |
61 | - context = Projects::ForkContext.new(from_project, user) | 61 | + context = Projects::ForkService.new(from_project, user) |
62 | shell = double("gitlab_shell") | 62 | shell = double("gitlab_shell") |
63 | shell.stub(fork_repository: true) | 63 | shell.stub(fork_repository: true) |
64 | context.stub(gitlab_shell: shell) | 64 | context.stub(gitlab_shell: shell) |
@@ -0,0 +1,57 @@ | @@ -0,0 +1,57 @@ | ||
1 | +require 'spec_helper' | ||
2 | + | ||
3 | +describe Projects::ForkService do | ||
4 | + describe :fork_by_user do | ||
5 | + before do | ||
6 | + @from_namespace = create(:namespace) | ||
7 | + @from_user = create(:user, namespace: @from_namespace ) | ||
8 | + @from_project = create(:project, creator_id: @from_user.id, namespace: @from_namespace) | ||
9 | + @to_namespace = create(:namespace) | ||
10 | + @to_user = create(:user, namespace: @to_namespace) | ||
11 | + end | ||
12 | + | ||
13 | + context 'fork project' do | ||
14 | + | ||
15 | + it "successfully creates project in the user namespace" do | ||
16 | + @to_project = fork_project(@from_project, @to_user) | ||
17 | + | ||
18 | + @to_project.owner.should == @to_user | ||
19 | + @to_project.namespace.should == @to_user.namespace | ||
20 | + end | ||
21 | + end | ||
22 | + | ||
23 | + context 'fork project failure' do | ||
24 | + | ||
25 | + it "fails due to transaction failure" do | ||
26 | + # make the mock gitlab-shell fail | ||
27 | + @to_project = fork_project(@from_project, @to_user, false) | ||
28 | + | ||
29 | + @to_project.errors.should_not be_empty | ||
30 | + @to_project.errors[:base].should include("Fork transaction failed.") | ||
31 | + end | ||
32 | + | ||
33 | + end | ||
34 | + | ||
35 | + context 'project already exists' do | ||
36 | + | ||
37 | + it "should fail due to validation, not transaction failure" do | ||
38 | + @existing_project = create(:project, creator_id: @to_user.id, name: @from_project.name, namespace: @to_namespace) | ||
39 | + @to_project = fork_project(@from_project, @to_user) | ||
40 | + | ||
41 | + @existing_project.persisted?.should be_true | ||
42 | + @to_project.errors[:base].should include("Invalid fork destination") | ||
43 | + @to_project.errors[:base].should_not include("Fork transaction failed.") | ||
44 | + end | ||
45 | + | ||
46 | + end | ||
47 | + end | ||
48 | + | ||
49 | + def fork_project(from_project, user, fork_success = true) | ||
50 | + context = Projects::ForkService.new(from_project, user) | ||
51 | + shell = double("gitlab_shell") | ||
52 | + shell.stub(fork_repository: fork_success) | ||
53 | + context.stub(gitlab_shell: shell) | ||
54 | + context.execute | ||
55 | + end | ||
56 | + | ||
57 | +end |
@@ -0,0 +1,113 @@ | @@ -0,0 +1,113 @@ | ||
1 | +require 'spec_helper' | ||
2 | + | ||
3 | +describe Issues::BulkUpdateService do | ||
4 | + before(:each) { ActiveRecord::Base.observers.enable(:user_observer) } | ||
5 | + after(:each) { ActiveRecord::Base.observers.disable(:user_observer) } | ||
6 | + | ||
7 | + let(:issue) { | ||
8 | + create(:issue, project: @project) | ||
9 | + } | ||
10 | + | ||
11 | + before do | ||
12 | + @user = create :user | ||
13 | + opts = { | ||
14 | + name: "GitLab", | ||
15 | + namespace: @user.namespace | ||
16 | + } | ||
17 | + @project = Projects::CreateService.new(@user, opts).execute | ||
18 | + end | ||
19 | + | ||
20 | + describe :close_issue do | ||
21 | + | ||
22 | + before do | ||
23 | + @issues = 5.times.collect do | ||
24 | + create(:issue, project: @project) | ||
25 | + end | ||
26 | + @params = { | ||
27 | + update: { | ||
28 | + status: 'closed', | ||
29 | + issues_ids: @issues.map(&:id) | ||
30 | + } | ||
31 | + } | ||
32 | + end | ||
33 | + | ||
34 | + it { | ||
35 | + result = Issues::BulkUpdateService.new(@project, @user, @params).execute | ||
36 | + result[:success].should be_true | ||
37 | + result[:count].should == @issues.count | ||
38 | + | ||
39 | + @project.issues.opened.should be_empty | ||
40 | + @project.issues.closed.should_not be_empty | ||
41 | + } | ||
42 | + | ||
43 | + end | ||
44 | + | ||
45 | + describe :reopen_issues do | ||
46 | + | ||
47 | + before do | ||
48 | + @issues = 5.times.collect do | ||
49 | + create(:closed_issue, project: @project) | ||
50 | + end | ||
51 | + @params = { | ||
52 | + update: { | ||
53 | + status: 'reopen', | ||
54 | + issues_ids: @issues.map(&:id) | ||
55 | + } | ||
56 | + } | ||
57 | + end | ||
58 | + | ||
59 | + it { | ||
60 | + result = Issues::BulkUpdateService.new(@project, @user, @params).execute | ||
61 | + result[:success].should be_true | ||
62 | + result[:count].should == @issues.count | ||
63 | + | ||
64 | + @project.issues.closed.should be_empty | ||
65 | + @project.issues.opened.should_not be_empty | ||
66 | + } | ||
67 | + | ||
68 | + end | ||
69 | + | ||
70 | + describe :update_assignee do | ||
71 | + | ||
72 | + before do | ||
73 | + @new_assignee = create :user | ||
74 | + @params = { | ||
75 | + update: { | ||
76 | + issues_ids: [issue.id], | ||
77 | + assignee_id: @new_assignee.id | ||
78 | + } | ||
79 | + } | ||
80 | + end | ||
81 | + | ||
82 | + it { | ||
83 | + result = Issues::BulkUpdateService.new(@project, @user, @params).execute | ||
84 | + result[:success].should be_true | ||
85 | + result[:count].should == 1 | ||
86 | + | ||
87 | + @project.issues.first.assignee.should == @new_assignee | ||
88 | + } | ||
89 | + | ||
90 | + end | ||
91 | + | ||
92 | + describe :update_milestone do | ||
93 | + | ||
94 | + before do | ||
95 | + @milestone = create :milestone | ||
96 | + @params = { | ||
97 | + update: { | ||
98 | + issues_ids: [issue.id], | ||
99 | + milestone_id: @milestone.id | ||
100 | + } | ||
101 | + } | ||
102 | + end | ||
103 | + | ||
104 | + it { | ||
105 | + result = Issues::BulkUpdateService.new(@project, @user, @params).execute | ||
106 | + result[:success].should be_true | ||
107 | + result[:count].should == 1 | ||
108 | + | ||
109 | + @project.issues.first.milestone.should == @milestone | ||
110 | + } | ||
111 | + end | ||
112 | + | ||
113 | +end |
@@ -0,0 +1,142 @@ | @@ -0,0 +1,142 @@ | ||
1 | +require 'spec_helper' | ||
2 | + | ||
3 | +describe Projects::CreateService do | ||
4 | + before(:each) { ActiveRecord::Base.observers.enable(:user_observer) } | ||
5 | + after(:each) { ActiveRecord::Base.observers.disable(:user_observer) } | ||
6 | + | ||
7 | + describe :create_by_user do | ||
8 | + before do | ||
9 | + @user = create :user | ||
10 | + @admin = create :user, admin: true | ||
11 | + @opts = { | ||
12 | + name: "GitLab", | ||
13 | + namespace: @user.namespace | ||
14 | + } | ||
15 | + end | ||
16 | + | ||
17 | + context 'user namespace' do | ||
18 | + before do | ||
19 | + @project = create_project(@user, @opts) | ||
20 | + end | ||
21 | + | ||
22 | + it { @project.should be_valid } | ||
23 | + it { @project.owner.should == @user } | ||
24 | + it { @project.namespace.should == @user.namespace } | ||
25 | + end | ||
26 | + | ||
27 | + context 'group namespace' do | ||
28 | + before do | ||
29 | + @group = create :group | ||
30 | + @group.add_owner(@user) | ||
31 | + | ||
32 | + @opts.merge!(namespace_id: @group.id) | ||
33 | + @project = create_project(@user, @opts) | ||
34 | + end | ||
35 | + | ||
36 | + it { @project.should be_valid } | ||
37 | + it { @project.owner.should == @group } | ||
38 | + it { @project.namespace.should == @group } | ||
39 | + end | ||
40 | + | ||
41 | + context 'respect configured visibility setting' do | ||
42 | + before(:each) do | ||
43 | + @settings = double("settings") | ||
44 | + @settings.stub(:issues) { true } | ||
45 | + @settings.stub(:merge_requests) { true } | ||
46 | + @settings.stub(:wiki) { true } | ||
47 | + @settings.stub(:wall) { true } | ||
48 | + @settings.stub(:snippets) { true } | ||
49 | + stub_const("Settings", Class.new) | ||
50 | + @restrictions = double("restrictions") | ||
51 | + @restrictions.stub(:restricted_visibility_levels) { [] } | ||
52 | + Settings.stub_chain(:gitlab).and_return(@restrictions) | ||
53 | + Settings.stub_chain(:gitlab, :default_projects_features).and_return(@settings) | ||
54 | + end | ||
55 | + | ||
56 | + context 'should be public when setting is public' do | ||
57 | + before do | ||
58 | + @settings.stub(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC } | ||
59 | + @project = create_project(@user, @opts) | ||
60 | + end | ||
61 | + | ||
62 | + it { @project.public?.should be_true } | ||
63 | + end | ||
64 | + | ||
65 | + context 'should be private when setting is private' do | ||
66 | + before do | ||
67 | + @settings.stub(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE } | ||
68 | + @project = create_project(@user, @opts) | ||
69 | + end | ||
70 | + | ||
71 | + it { @project.private?.should be_true } | ||
72 | + end | ||
73 | + | ||
74 | + context 'should be internal when setting is internal' do | ||
75 | + before do | ||
76 | + @settings.stub(:visibility_level) { Gitlab::VisibilityLevel::INTERNAL } | ||
77 | + @project = create_project(@user, @opts) | ||
78 | + end | ||
79 | + | ||
80 | + it { @project.internal?.should be_true } | ||
81 | + end | ||
82 | + end | ||
83 | + | ||
84 | + context 'respect configured visibility restrictions setting' do | ||
85 | + before(:each) do | ||
86 | + @settings = double("settings") | ||
87 | + @settings.stub(:issues) { true } | ||
88 | + @settings.stub(:merge_requests) { true } | ||
89 | + @settings.stub(:wiki) { true } | ||
90 | + @settings.stub(:wall) { true } | ||
91 | + @settings.stub(:snippets) { true } | ||
92 | + @settings.stub(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE } | ||
93 | + stub_const("Settings", Class.new) | ||
94 | + @restrictions = double("restrictions") | ||
95 | + @restrictions.stub(:restricted_visibility_levels) { [ Gitlab::VisibilityLevel::PUBLIC ] } | ||
96 | + Settings.stub_chain(:gitlab).and_return(@restrictions) | ||
97 | + Settings.stub_chain(:gitlab, :default_projects_features).and_return(@settings) | ||
98 | + end | ||
99 | + | ||
100 | + context 'should be private when option is public' do | ||
101 | + before do | ||
102 | + @opts.merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) | ||
103 | + @project = create_project(@user, @opts) | ||
104 | + end | ||
105 | + | ||
106 | + it { @project.private?.should be_true } | ||
107 | + end | ||
108 | + | ||
109 | + context 'should be public when option is public for admin' do | ||
110 | + before do | ||
111 | + @opts.merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) | ||
112 | + @project = create_project(@admin, @opts) | ||
113 | + end | ||
114 | + | ||
115 | + it { @project.public?.should be_true } | ||
116 | + end | ||
117 | + | ||
118 | + context 'should be private when option is private' do | ||
119 | + before do | ||
120 | + @opts.merge!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) | ||
121 | + @project = create_project(@user, @opts) | ||
122 | + end | ||
123 | + | ||
124 | + it { @project.private?.should be_true } | ||
125 | + end | ||
126 | + | ||
127 | + context 'should be internal when option is internal' do | ||
128 | + before do | ||
129 | + @opts.merge!(visibility_level: Gitlab::VisibilityLevel::INTERNAL) | ||
130 | + @project = create_project(@user, @opts) | ||
131 | + end | ||
132 | + | ||
133 | + it { @project.internal?.should be_true } | ||
134 | + end | ||
135 | + end | ||
136 | + end | ||
137 | + | ||
138 | + def create_project(user, opts) | ||
139 | + Projects::CreateService.new(user, opts).execute | ||
140 | + end | ||
141 | +end | ||
142 | + |
@@ -0,0 +1,111 @@ | @@ -0,0 +1,111 @@ | ||
1 | +require 'spec_helper' | ||
2 | + | ||
3 | +describe Projects::UpdateService do | ||
4 | + before(:each) { ActiveRecord::Base.observers.enable(:user_observer) } | ||
5 | + after(:each) { ActiveRecord::Base.observers.disable(:user_observer) } | ||
6 | + | ||
7 | + describe :update_by_user do | ||
8 | + before do | ||
9 | + @user = create :user | ||
10 | + @admin = create :user, admin: true | ||
11 | + @project = create :project, creator_id: @user.id, namespace: @user.namespace | ||
12 | + @opts = { project: {} } | ||
13 | + end | ||
14 | + | ||
15 | + context 'should be private when updated to private' do | ||
16 | + before do | ||
17 | + @created_private = @project.private? | ||
18 | + | ||
19 | + @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) | ||
20 | + update_project(@project, @user, @opts) | ||
21 | + end | ||
22 | + | ||
23 | + it { @created_private.should be_true } | ||
24 | + it { @project.private?.should be_true } | ||
25 | + end | ||
26 | + | ||
27 | + context 'should be internal when updated to internal' do | ||
28 | + before do | ||
29 | + @created_private = @project.private? | ||
30 | + | ||
31 | + @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::INTERNAL) | ||
32 | + update_project(@project, @user, @opts) | ||
33 | + end | ||
34 | + | ||
35 | + it { @created_private.should be_true } | ||
36 | + it { @project.internal?.should be_true } | ||
37 | + end | ||
38 | + | ||
39 | + context 'should be public when updated to public' do | ||
40 | + before do | ||
41 | + @created_private = @project.private? | ||
42 | + | ||
43 | + @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) | ||
44 | + update_project(@project, @user, @opts) | ||
45 | + end | ||
46 | + | ||
47 | + it { @created_private.should be_true } | ||
48 | + it { @project.public?.should be_true } | ||
49 | + end | ||
50 | + | ||
51 | + context 'respect configured visibility restrictions setting' do | ||
52 | + before(:each) do | ||
53 | + @restrictions = double("restrictions") | ||
54 | + @restrictions.stub(:restricted_visibility_levels) { [ Gitlab::VisibilityLevel::PUBLIC ] } | ||
55 | + Settings.stub_chain(:gitlab).and_return(@restrictions) | ||
56 | + end | ||
57 | + | ||
58 | + context 'should be private when updated to private' do | ||
59 | + before do | ||
60 | + @created_private = @project.private? | ||
61 | + | ||
62 | + @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) | ||
63 | + update_project(@project, @user, @opts) | ||
64 | + end | ||
65 | + | ||
66 | + it { @created_private.should be_true } | ||
67 | + it { @project.private?.should be_true } | ||
68 | + end | ||
69 | + | ||
70 | + context 'should be internal when updated to internal' do | ||
71 | + before do | ||
72 | + @created_private = @project.private? | ||
73 | + | ||
74 | + @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::INTERNAL) | ||
75 | + update_project(@project, @user, @opts) | ||
76 | + end | ||
77 | + | ||
78 | + it { @created_private.should be_true } | ||
79 | + it { @project.internal?.should be_true } | ||
80 | + end | ||
81 | + | ||
82 | + context 'should be private when updated to public' do | ||
83 | + before do | ||
84 | + @created_private = @project.private? | ||
85 | + | ||
86 | + @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) | ||
87 | + update_project(@project, @user, @opts) | ||
88 | + end | ||
89 | + | ||
90 | + it { @created_private.should be_true } | ||
91 | + it { @project.private?.should be_true } | ||
92 | + end | ||
93 | + | ||
94 | + context 'should be public when updated to public by admin' do | ||
95 | + before do | ||
96 | + @created_private = @project.private? | ||
97 | + | ||
98 | + @opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) | ||
99 | + update_project(@project, @admin, @opts) | ||
100 | + end | ||
101 | + | ||
102 | + it { @created_private.should be_true } | ||
103 | + it { @project.public?.should be_true } | ||
104 | + end | ||
105 | + end | ||
106 | + end | ||
107 | + | ||
108 | + def update_project(project, user, opts) | ||
109 | + Projects::UpdateService.new(project, user, opts).execute | ||
110 | + end | ||
111 | +end |
@@ -0,0 +1,54 @@ | @@ -0,0 +1,54 @@ | ||
1 | +require 'spec_helper' | ||
2 | + | ||
3 | +describe 'Search::GlobalService' do | ||
4 | + let(:found_namespace) { create(:namespace, name: 'searchable namespace', path:'another_thing') } | ||
5 | + let(:user) { create(:user, namespace: found_namespace) } | ||
6 | + let!(:found_project) { create(:project, name: 'searchable_project', creator_id: user.id, namespace: found_namespace, visibility_level: Gitlab::VisibilityLevel::PRIVATE) } | ||
7 | + | ||
8 | + let(:unfound_namespace) { create(:namespace, name: 'unfound namespace', path: 'yet_something_else') } | ||
9 | + let!(:unfound_project) { create(:project, name: 'unfound_project', creator_id: user.id, namespace: unfound_namespace, visibility_level: Gitlab::VisibilityLevel::PRIVATE) } | ||
10 | + | ||
11 | + let(:internal_namespace) { create(:namespace, path: 'something_internal',name: 'searchable internal namespace') } | ||
12 | + let(:internal_user) { create(:user, namespace: internal_namespace) } | ||
13 | + let!(:internal_project) { create(:project, name: 'searchable_internal_project', creator_id: internal_user.id, namespace: internal_namespace, visibility_level: Gitlab::VisibilityLevel::INTERNAL) } | ||
14 | + | ||
15 | + let(:public_namespace) { create(:namespace, path: 'something_public',name: 'searchable public namespace') } | ||
16 | + let(:public_user) { create(:user, namespace: public_namespace) } | ||
17 | + let!(:public_project) { create(:project, name: 'searchable_public_project', creator_id: public_user.id, namespace: public_namespace, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } | ||
18 | + | ||
19 | + describe '#execute' do | ||
20 | + context 'unauthenticated' do | ||
21 | + it 'should return public projects only' do | ||
22 | + context = Search::GlobalService.new(nil, search: "searchable") | ||
23 | + results = context.execute | ||
24 | + results[:projects].should have(1).items | ||
25 | + results[:projects].should include(public_project) | ||
26 | + end | ||
27 | + end | ||
28 | + | ||
29 | + context 'authenticated' do | ||
30 | + it 'should return public, internal and private projects' do | ||
31 | + context = Search::GlobalService.new(user, search: "searchable") | ||
32 | + results = context.execute | ||
33 | + results[:projects].should have(3).items | ||
34 | + results[:projects].should include(public_project) | ||
35 | + results[:projects].should include(found_project) | ||
36 | + results[:projects].should include(internal_project) | ||
37 | + end | ||
38 | + | ||
39 | + it 'should return only public & internal projects' do | ||
40 | + context = Search::GlobalService.new(internal_user, search: "searchable") | ||
41 | + results = context.execute | ||
42 | + results[:projects].should have(2).items | ||
43 | + results[:projects].should include(internal_project) | ||
44 | + results[:projects].should include(public_project) | ||
45 | + end | ||
46 | + | ||
47 | + it 'namespace name should be searchable' do | ||
48 | + context = Search::GlobalService.new(user, search: "searchable namespace") | ||
49 | + results = context.execute | ||
50 | + results[:projects].should == [found_project] | ||
51 | + end | ||
52 | + end | ||
53 | + end | ||
54 | +end |