Commit f0d2d28118354b6362988687757b63dc7be611e5

Authored by Dmitriy Zaporozhets
2 parents 7527408a 4d82e9ed

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
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -module Notes  
2 - class CreateContext < BaseContext  
3 - def execute  
4 - note = project.notes.new(params[:note])  
5 - note.author = current_user  
6 - note.save  
7 - note  
8 - end  
9 - end  
10 -end  
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 &lt; Admin::ApplicationController @@ -19,7 +19,7 @@ class Admin::ProjectsController &lt; 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 &lt; Projects::ApplicationController @@ -13,7 +13,7 @@ class Projects::BlobController &lt; 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 &lt; Projects::BaseTreeController @@ -7,7 +7,7 @@ class Projects::EditTreeController &lt; 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 &lt; Projects::ApplicationController @@ -89,7 +89,7 @@ class Projects::IssuesController &lt; 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 &lt; Projects::BaseTreeController @@ -6,7 +6,7 @@ class Projects::NewTreeController &lt; 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 &lt; Projects::ApplicationController @@ -5,7 +5,7 @@ class Projects::NotesController &lt; 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 &lt; Projects::ApplicationController @@ -20,7 +20,7 @@ class Projects::NotesController &lt; 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 &lt; ApplicationController @@ -20,7 +20,7 @@ class ProjectsController &lt; 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 &lt; ApplicationController @@ -36,7 +36,7 @@ class ProjectsController &lt; 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 &lt; ApplicationController @@ -51,7 +51,7 @@ class ProjectsController &lt; 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 &lt; ApplicationController @@ -89,7 +89,7 @@ class ProjectsController &lt; 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 &lt; ApplicationController @@ -5,9 +5,9 @@ class SearchController &lt; 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
app/services/base_service.rb 0 → 100644
@@ -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
app/services/files/base_service.rb 0 → 100644
@@ -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
app/services/files/create_service.rb 0 → 100644
@@ -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
app/services/files/delete_service.rb 0 → 100644
@@ -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
app/services/files/update_service.rb 0 → 100644
@@ -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
app/services/issues/bulk_update_service.rb 0 → 100644
@@ -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
app/services/notes/create_service.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +module Notes
  2 + class CreateService < BaseService
  3 + def execute
  4 + note = project.notes.new(params[:note])
  5 + note.author = current_user
  6 + note.save
  7 + note
  8 + end
  9 + end
  10 +end
app/services/notes/load_service.rb 0 → 100644
@@ -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
app/services/projects/create_service.rb 0 → 100644
@@ -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
app/services/projects/fork_service.rb 0 → 100644
@@ -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
app/services/projects/transfer_service.rb 0 → 100644
@@ -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 +
app/services/projects/update_service.rb 0 → 100644
@@ -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
app/services/search/global_service.rb 0 → 100644
@@ -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
app/services/search/project_service.rb 0 → 100644
@@ -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)
spec/services/fork_service_spec.rb 0 → 100644
@@ -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
spec/services/issues/bulk_update_context_spec.rb 0 → 100644
@@ -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
spec/services/projects_create_service_spec.rb 0 → 100644
@@ -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 +
spec/services/projects_update_service_spec.rb 0 → 100644
@@ -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
spec/services/search_service_spec.rb 0 → 100644
@@ -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