diff options
Diffstat (limited to 'lib/api')
-rw-r--r-- | lib/api/api.rb | 1 | ||||
-rw-r--r-- | lib/api/deploy_keys.rb | 10 | ||||
-rw-r--r-- | lib/api/entities.rb | 25 | ||||
-rw-r--r-- | lib/api/groups.rb | 17 | ||||
-rw-r--r-- | lib/api/helpers.rb | 24 | ||||
-rw-r--r-- | lib/api/internal.rb | 1 | ||||
-rw-r--r-- | lib/api/issues.rb | 39 | ||||
-rw-r--r-- | lib/api/merge_requests.rb | 79 | ||||
-rw-r--r-- | lib/api/milestones.rb | 34 | ||||
-rw-r--r-- | lib/api/notes.rb | 40 | ||||
-rw-r--r-- | lib/api/projects.rb | 12 | ||||
-rw-r--r-- | lib/api/repositories.rb | 30 | ||||
-rw-r--r-- | lib/api/services.rb | 44 |
13 files changed, 234 insertions, 122 deletions
diff --git a/lib/api/api.rb b/lib/api/api.rb index c4c9f166db1..4db81f42b4c 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -38,5 +38,6 @@ module API mount ProjectSnippets mount DeployKeys mount ProjectHooks + mount Services end end diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb index 218b3d8eee2..b5997608997 100644 --- a/lib/api/deploy_keys.rb +++ b/lib/api/deploy_keys.rb @@ -5,16 +5,6 @@ module API before { authorize_admin_project } resource :projects do - helpers do - def handle_project_member_errors(errors) - if errors[:project_access].any? - error!(errors[:project_access], 422) - end - not_found! - end - end - - # Get a specific project's keys # # Example Request: diff --git a/lib/api/entities.rb b/lib/api/entities.rb index ab949f530ab..429083d75be 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -91,15 +91,16 @@ module API expose :expires_at, :updated_at, :created_at end - class Milestone < Grape::Entity - expose :id - expose (:project_id) {|milestone| milestone.project.id} + class ProjectEntity < Grape::Entity + expose :id, :iid + expose (:project_id) { |entity| entity.project.id } + end + + class Milestone < ProjectEntity expose :title, :description, :due_date, :state, :updated_at, :created_at end - class Issue < Grape::Entity - expose :id - expose (:project_id) {|issue| issue.project.id} + class Issue < ProjectEntity expose :title, :description expose :label_list, as: :labels expose :milestone, using: Entities::Milestone @@ -107,14 +108,14 @@ module API expose :state, :updated_at, :created_at end - class SSHKey < Grape::Entity - expose :id, :title, :key, :created_at + class MergeRequest < ProjectEntity + expose :target_branch, :source_branch, :title, :state, :upvotes, :downvotes + expose :author, :assignee, using: Entities::UserBasic + expose :source_project_id, :target_project_id end - class MergeRequest < Grape::Entity - expose :id, :target_branch, :source_branch, :title, :state - expose :target_project_id, as: :project_id - expose :author, :assignee, using: Entities::UserBasic + class SSHKey < Grape::Entity + expose :id, :title, :key, :created_at end class Note < Grape::Entity diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 396554404af..290b78d8017 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -7,12 +7,14 @@ module API helpers do def find_group(id) group = Group.find(id) - if current_user.admin or current_user.groups.include? group + + if can?(current_user, :read_group, group) group else render_api_error!("403 Forbidden - #{current_user.username} lacks sufficient access to #{group.name}", 403) end end + def validate_access_level?(level) Gitlab::Access.options_with_owner.values.include? level.to_i end @@ -64,6 +66,18 @@ module API present group, with: Entities::GroupDetail end + # Remove group + # + # Parameters: + # id (required) - The ID of a group + # Example Request: + # DELETE /groups/:id + delete ":id" do + group = find_group(params[:id]) + authorize! :manage_group, group + group.destroy + end + # Transfer a project to the Group namespace # # Parameters: @@ -132,7 +146,6 @@ module API member.destroy end end - end end end diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 2b0c672c7fa..b0f8d5a6da9 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -6,23 +6,23 @@ module API SUDO_PARAM = :sudo def current_user - @current_user ||= User.find_by_authentication_token(params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]) + private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s + @current_user ||= User.find_by_authentication_token(private_token) identifier = sudo_identifier() + # If the sudo is the current user do nothing if (identifier && !(@current_user.id == identifier || @current_user.username == identifier)) render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin? - begin - @current_user = User.by_username_or_id(identifier) - rescue => ex - not_found!("No user id or username for: #{identifier}") - end - not_found!("No user id or username for: #{identifier}") if current_user.nil? + @current_user = User.by_username_or_id(identifier) + not_found!("No user id or username for: #{identifier}") if @current_user.nil? end + @current_user end def sudo_identifier() identifier ||= params[SUDO_PARAM] ||= env[SUDO_HEADER] + # Regex for integers if (!!(identifier =~ /^[0-9]+$/)) identifier.to_i @@ -31,6 +31,16 @@ module API end end + def set_current_user_for_thread + Thread.current[:current_user] = current_user + + begin + yield + ensure + Thread.current[:current_user] = nil + end + end + def user_project @project ||= find_project(params[:id]) @project || not_found! diff --git a/lib/api/internal.rb b/lib/api/internal.rb index 79f8eb3a543..ed6b50c3a6a 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -35,6 +35,7 @@ module API user = key.user return false if user.blocked? + return false if user.ldap_user? && Gitlab::LDAP::User.blocked?(user.extern_uid) action = case git_cmd when *DOWNLOAD_COMMANDS diff --git a/lib/api/issues.rb b/lib/api/issues.rb index a15203d1563..3d15c35b8cc 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -2,7 +2,6 @@ module API # Issues API class Issues < Grape::API before { authenticate! } - before { Thread.current[:current_user] = current_user } resource :issues do # Get currently authenticated user's issues @@ -49,15 +48,17 @@ module API # Example Request: # POST /projects/:id/issues post ":id/issues" do - required_attributes! [:title] - attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id] - attrs[:label_list] = params[:labels] if params[:labels].present? - @issue = user_project.issues.new attrs - @issue.author = current_user - if @issue.save - present @issue, with: Entities::Issue - else - not_found! + set_current_user_for_thread do + required_attributes! [:title] + attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id] + attrs[:label_list] = params[:labels] if params[:labels].present? + @issue = user_project.issues.new attrs + @issue.author = current_user + if @issue.save + present @issue, with: Entities::Issue + else + not_found! + end end end @@ -75,16 +76,18 @@ module API # Example Request: # PUT /projects/:id/issues/:issue_id put ":id/issues/:issue_id" do - @issue = user_project.issues.find(params[:issue_id]) - authorize! :modify_issue, @issue + set_current_user_for_thread do + @issue = user_project.issues.find(params[:issue_id]) + authorize! :modify_issue, @issue - attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :state_event] - attrs[:label_list] = params[:labels] if params[:labels].present? + attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :state_event] + attrs[:label_list] = params[:labels] if params[:labels].present? - if @issue.update_attributes attrs - present @issue, with: Entities::Issue - else - not_found! + if @issue.update_attributes attrs + present @issue, with: Entities::Issue + else + not_found! + end end end diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index d690f1d07e7..3f4bec895bf 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -2,7 +2,6 @@ module API # MergeRequest API class MergeRequests < Grape::API before { authenticate! } - before { Thread.current[:current_user] = current_user } resource :projects do helpers do @@ -70,28 +69,30 @@ module API # POST /projects/:id/merge_requests # post ":id/merge_requests" do - authorize! :write_merge_request, user_project - required_attributes! [:source_branch, :target_branch, :title] - attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :target_project_id] - merge_request = user_project.merge_requests.new(attrs) - merge_request.author = current_user - merge_request.source_project = user_project - target_project_id = attrs[:target_project_id] - if not_fork?(target_project_id, user_project) - merge_request.target_project = user_project - else - if target_matches_fork(target_project_id,user_project) - merge_request.target_project = Project.find_by_id(attrs[:target_project_id]) + set_current_user_for_thread do + authorize! :write_merge_request, user_project + required_attributes! [:source_branch, :target_branch, :title] + attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :target_project_id] + merge_request = user_project.merge_requests.new(attrs) + merge_request.author = current_user + merge_request.source_project = user_project + target_project_id = attrs[:target_project_id] + if not_fork?(target_project_id, user_project) + merge_request.target_project = user_project else - render_api_error!('(Bad Request) Specified target project that is not the source project, or the source fork of the project.', 400) + if target_matches_fork(target_project_id,user_project) + merge_request.target_project = Project.find_by_id(attrs[:target_project_id]) + else + render_api_error!('(Bad Request) Specified target project that is not the source project, or the source fork of the project.', 400) + end end - end - if merge_request.save - merge_request.reload_code - present merge_request, with: Entities::MergeRequest - else - handle_merge_request_errors! merge_request.errors + if merge_request.save + merge_request.reload_code + present merge_request, with: Entities::MergeRequest + else + handle_merge_request_errors! merge_request.errors + end end end @@ -109,17 +110,19 @@ module API # PUT /projects/:id/merge_request/:merge_request_id # put ":id/merge_request/:merge_request_id" do - attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event] - merge_request = user_project.merge_requests.find(params[:merge_request_id]) + set_current_user_for_thread do + attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event] + merge_request = user_project.merge_requests.find(params[:merge_request_id]) - authorize! :modify_merge_request, merge_request + authorize! :modify_merge_request, merge_request - if merge_request.update_attributes attrs - merge_request.reload_code - merge_request.mark_as_unchecked - present merge_request, with: Entities::MergeRequest - else - handle_merge_request_errors! merge_request.errors + if merge_request.update_attributes attrs + merge_request.reload_code + merge_request.mark_as_unchecked + present merge_request, with: Entities::MergeRequest + else + handle_merge_request_errors! merge_request.errors + end end end @@ -133,16 +136,18 @@ module API # POST /projects/:id/merge_request/:merge_request_id/comments # post ":id/merge_request/:merge_request_id/comments" do - required_attributes! [:note] + set_current_user_for_thread do + required_attributes! [:note] - merge_request = user_project.merge_requests.find(params[:merge_request_id]) - note = merge_request.notes.new(note: params[:note], project_id: user_project.id) - note.author = current_user + merge_request = user_project.merge_requests.find(params[:merge_request_id]) + note = merge_request.notes.new(note: params[:note], project_id: user_project.id) + note.author = current_user - if note.save - present note, with: Entities::MRNote - else - not_found! + if note.save + present note, with: Entities::MRNote + else + not_found! + end end end diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb index aee12e7dc40..f7e63b23093 100644 --- a/lib/api/milestones.rb +++ b/lib/api/milestones.rb @@ -40,15 +40,17 @@ module API # Example Request: # POST /projects/:id/milestones post ":id/milestones" do - authorize! :admin_milestone, user_project - required_attributes! [:title] + set_current_user_for_thread do + authorize! :admin_milestone, user_project + required_attributes! [:title] - attrs = attributes_for_keys [:title, :description, :due_date] - @milestone = user_project.milestones.new attrs - if @milestone.save - present @milestone, with: Entities::Milestone - else - not_found! + attrs = attributes_for_keys [:title, :description, :due_date] + @milestone = user_project.milestones.new attrs + if @milestone.save + present @milestone, with: Entities::Milestone + else + not_found! + end end end @@ -64,14 +66,16 @@ module API # Example Request: # PUT /projects/:id/milestones/:milestone_id put ":id/milestones/:milestone_id" do - authorize! :admin_milestone, user_project + set_current_user_for_thread do + authorize! :admin_milestone, user_project - @milestone = user_project.milestones.find(params[:milestone_id]) - attrs = attributes_for_keys [:title, :description, :due_date, :state_event] - if @milestone.update_attributes attrs - present @milestone, with: Entities::Milestone - else - not_found! + @milestone = user_project.milestones.find(params[:milestone_id]) + attrs = attributes_for_keys [:title, :description, :due_date, :state_event] + if @milestone.update_attributes attrs + present @milestone, with: Entities::Milestone + else + not_found! + end end end end diff --git a/lib/api/notes.rb b/lib/api/notes.rb index cb2bc764476..f21907b1ffc 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -41,17 +41,19 @@ module API # Example Request: # POST /projects/:id/notes post ":id/notes" do - required_attributes! [:body] + set_current_user_for_thread do + required_attributes! [:body] - @note = user_project.notes.new(note: params[:body]) - @note.author = current_user + @note = user_project.notes.new(note: params[:body]) + @note.author = current_user - if @note.save - present @note, with: Entities::Note - else - # :note is exposed as :body, but :note is set on error - bad_request!(:note) if @note.errors[:note].any? - not_found! + if @note.save + present @note, with: Entities::Note + else + # :note is exposed as :body, but :note is set on error + bad_request!(:note) if @note.errors[:note].any? + not_found! + end end end @@ -97,17 +99,19 @@ module API # POST /projects/:id/issues/:noteable_id/notes # POST /projects/:id/snippets/:noteable_id/notes post ":id/#{noteables_str}/:#{noteable_id_str}/notes" do - required_attributes! [:body] + set_current_user_for_thread do + required_attributes! [:body] - @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"]) - @note = @noteable.notes.new(note: params[:body]) - @note.author = current_user - @note.project = user_project + @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"]) + @note = @noteable.notes.new(note: params[:body]) + @note.author = current_user + @note.project = user_project - if @note.save - present @note, with: Entities::Note - else - not_found! + if @note.save + present @note, with: Entities::Note + else + not_found! + end end end end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index cf357b23c40..42560572046 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -60,7 +60,6 @@ module API # Parameters: # name (required) - name for new project # description (optional) - short project description - # default_branch (optional) - 'master' by default # issues_enabled (optional) # wall_enabled (optional) # merge_requests_enabled (optional) @@ -75,7 +74,6 @@ module API attrs = attributes_for_keys [:name, :path, :description, - :default_branch, :issues_enabled, :wall_enabled, :merge_requests_enabled, @@ -129,6 +127,16 @@ module API end end + # Remove project + # + # Parameters: + # id (required) - The ID of a project + # Example Request: + # DELETE /projects/:id + delete ":id" do + authorize! :remove_project, user_project + user_project.destroy + end # Mark this project as forked from another # diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 1a911eae2bb..c9422fdb165 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -144,7 +144,7 @@ module API trees = [] %w(trees blobs submodules).each do |type| - trees += tree.send(type).map { |t| { name: t.name, type: type.singularize, mode: t.mode, id: t.id } } + trees += tree.send(type).map { |t| {name: t.name, type: type.singularize, mode: t.mode, id: t.id} } end trees @@ -176,6 +176,34 @@ module API content_type blob.mime_type present blob.data end + + # Get a an archive of the repository + # + # Parameters: + # id (required) - The ID of a project + # sha (optional) - the commit sha to download defaults to the tip of the default branch + # Example Request: + # GET /projects/:id/repository/archive + get ":id/repository/archive" do + authorize! :download_code, user_project + repo = user_project.repository + ref = params[:sha] + storage_path = Rails.root.join("tmp", "repositories") + + file_path = repo.archive_repo(ref, storage_path) + if file_path && File.exists?(file_path) + data = File.open(file_path, 'rb').read + + header "Content-Disposition:", " infile; filename=\"#{File.basename(file_path)}\"" + content_type 'application/x-gzip' + + env['api.format'] = :binary + + present data + else + not_found! + end + end end end end diff --git a/lib/api/services.rb b/lib/api/services.rb new file mode 100644 index 00000000000..bde502e32e1 --- /dev/null +++ b/lib/api/services.rb @@ -0,0 +1,44 @@ +module API + # Projects API + class Services < Grape::API + before { authenticate! } + before { authorize_admin_project } + + resource :projects do + # Set GitLab CI service for project + # + # Parameters: + # token (required) - CI project token + # project_url (required) - CI project url + # + # Example Request: + # PUT /projects/:id/services/gitlab-ci + put ":id/services/gitlab-ci" do + required_attributes! [:token, :project_url] + attrs = attributes_for_keys [:token, :project_url] + user_project.build_missing_services + + if user_project.gitlab_ci_service.update_attributes(attrs.merge(active: true)) + true + else + not_found! + end + end + + # Delete GitLab CI service settings + # + # Example Request: + # DELETE /projects/:id/keys/:id + delete ":id/services/gitlab-ci" do + if user_project.gitlab_ci_service + user_project.gitlab_ci_service.update_attributes( + active: false, + token: nil, + project_url: nil + ) + end + end + end + end +end + |