summaryrefslogtreecommitdiff
path: root/lib/api
diff options
context:
space:
mode:
authorTimothy Andrew <mail@timothyandrew.net>2016-09-07 14:58:01 +0530
committerTimothy Andrew <mail@timothyandrew.net>2016-09-07 14:58:01 +0530
commitf5b9837c19f48255237eca1e618fc632a45b58b5 (patch)
tree2653e9aa1e3bf0a1db6630bb52863c30e6313d87 /lib/api
parent72b9b87ca93615640dcc022f324b2af16ceaa4eb (diff)
parent1d5488699678d22644d24add4b89cede0419ad25 (diff)
downloadgitlab-ce-f5b9837c19f48255237eca1e618fc632a45b58b5.tar.gz
Merge remote-tracking branch 'origin/master' into 21170-cycle-analytics
Diffstat (limited to 'lib/api')
-rw-r--r--lib/api/api.rb1
-rw-r--r--lib/api/award_emoji.rb6
-rw-r--r--lib/api/broadcast_messages.rb99
-rw-r--r--lib/api/commit_statuses.rb2
-rw-r--r--lib/api/entities.rb22
-rw-r--r--lib/api/groups.rb4
-rw-r--r--lib/api/helpers.rb12
-rw-r--r--lib/api/internal.rb14
-rw-r--r--lib/api/issues.rb34
-rw-r--r--lib/api/projects.rb32
-rw-r--r--lib/api/users.rb2
11 files changed, 181 insertions, 47 deletions
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 4602e627fdb..e14464c1b0d 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -31,6 +31,7 @@ module API
mount ::API::AccessRequests
mount ::API::AwardEmoji
mount ::API::Branches
+ mount ::API::BroadcastMessages
mount ::API::Builds
mount ::API::CommitStatuses
mount ::API::Commits
diff --git a/lib/api/award_emoji.rb b/lib/api/award_emoji.rb
index 2efe7e3adf3..7c22b17e4e5 100644
--- a/lib/api/award_emoji.rb
+++ b/lib/api/award_emoji.rb
@@ -54,7 +54,7 @@ module API
post endpoint do
required_attributes! [:name]
- not_found!('Award Emoji') unless can_read_awardable?
+ not_found!('Award Emoji') unless can_read_awardable? && can_award_awardable?
award = awardable.create_award_emoji(params[:name], current_user)
@@ -92,6 +92,10 @@ module API
can?(current_user, ability, awardable)
end
+ def can_award_awardable?
+ awardable.user_can_award?(current_user, params[:name])
+ end
+
def awardable
@awardable ||=
begin
diff --git a/lib/api/broadcast_messages.rb b/lib/api/broadcast_messages.rb
new file mode 100644
index 00000000000..fb2a4148011
--- /dev/null
+++ b/lib/api/broadcast_messages.rb
@@ -0,0 +1,99 @@
+module API
+ class BroadcastMessages < Grape::API
+ before { authenticate! }
+ before { authenticated_as_admin! }
+
+ resource :broadcast_messages do
+ helpers do
+ def find_message
+ BroadcastMessage.find(params[:id])
+ end
+ end
+
+ desc 'Get all broadcast messages' do
+ detail 'This feature was introduced in GitLab 8.12.'
+ success Entities::BroadcastMessage
+ end
+ params do
+ optional :page, type: Integer, desc: 'Current page number'
+ optional :per_page, type: Integer, desc: 'Number of messages per page'
+ end
+ get do
+ messages = BroadcastMessage.all
+
+ present paginate(messages), with: Entities::BroadcastMessage
+ end
+
+ desc 'Create a broadcast message' do
+ detail 'This feature was introduced in GitLab 8.12.'
+ success Entities::BroadcastMessage
+ end
+ params do
+ requires :message, type: String, desc: 'Message to display'
+ optional :starts_at, type: DateTime, desc: 'Starting time', default: -> { Time.zone.now }
+ optional :ends_at, type: DateTime, desc: 'Ending time', default: -> { 1.hour.from_now }
+ optional :color, type: String, desc: 'Background color'
+ optional :font, type: String, desc: 'Foreground color'
+ end
+ post do
+ create_params = declared(params, include_missing: false).to_h
+ message = BroadcastMessage.create(create_params)
+
+ if message.persisted?
+ present message, with: Entities::BroadcastMessage
+ else
+ render_validation_error!(message)
+ end
+ end
+
+ desc 'Get a specific broadcast message' do
+ detail 'This feature was introduced in GitLab 8.12.'
+ success Entities::BroadcastMessage
+ end
+ params do
+ requires :id, type: Integer, desc: 'Broadcast message ID'
+ end
+ get ':id' do
+ message = find_message
+
+ present message, with: Entities::BroadcastMessage
+ end
+
+ desc 'Update a broadcast message' do
+ detail 'This feature was introduced in GitLab 8.12.'
+ success Entities::BroadcastMessage
+ end
+ params do
+ requires :id, type: Integer, desc: 'Broadcast message ID'
+ optional :message, type: String, desc: 'Message to display'
+ optional :starts_at, type: DateTime, desc: 'Starting time'
+ optional :ends_at, type: DateTime, desc: 'Ending time'
+ optional :color, type: String, desc: 'Background color'
+ optional :font, type: String, desc: 'Foreground color'
+ end
+ put ':id' do
+ message = find_message
+ update_params = declared(params, include_missing: false).to_h
+
+ if message.update(update_params)
+ present message, with: Entities::BroadcastMessage
+ else
+ render_validation_error!(message)
+ end
+ end
+
+ desc 'Delete a broadcast message' do
+ detail 'This feature was introduced in GitLab 8.12.'
+ success Entities::BroadcastMessage
+ end
+ params do
+ requires :id, type: Integer, desc: 'Broadcast message ID'
+ end
+ delete ':id' do
+ message = find_message
+
+ present message.destroy, with: Entities::BroadcastMessage
+ end
+ end
+ end
+end
diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb
index 4df6ca8333e..5e3c9563703 100644
--- a/lib/api/commit_statuses.rb
+++ b/lib/api/commit_statuses.rb
@@ -64,7 +64,7 @@ module API
ref = branches.first
end
- pipeline = @project.ensure_pipeline(commit.sha, ref, current_user)
+ pipeline = @project.ensure_pipeline(ref, commit.sha, current_user)
name = params[:name] || params[:context]
status = GenericCommitStatus.running_or_pending.find_by(pipeline: pipeline, name: name, ref: params[:ref])
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index cbb324dd06d..3faba79415b 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -76,15 +76,23 @@ module API
expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
expose :name, :name_with_namespace
expose :path, :path_with_namespace
- expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :builds_enabled, :snippets_enabled, :container_registry_enabled
+ expose :container_registry_enabled
+
+ # Expose old field names with the new permissions methods to keep API compatible
+ expose(:issues_enabled) { |project, options| project.feature_available?(:issues, options[:user]) }
+ expose(:merge_requests_enabled) { |project, options| project.feature_available?(:merge_requests, options[:user]) }
+ expose(:wiki_enabled) { |project, options| project.feature_available?(:wiki, options[:user]) }
+ expose(:builds_enabled) { |project, options| project.feature_available?(:builds, options[:user]) }
+ expose(:snippets_enabled) { |project, options| project.feature_available?(:snippets, options[:user]) }
+
expose :created_at, :last_activity_at
- expose :shared_runners_enabled
+ expose :shared_runners_enabled, :lfs_enabled
expose :creator_id
expose :namespace
expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda{ |project, options| project.forked? }
expose :avatar_url
expose :star_count, :forks_count
- expose :open_issues_count, if: lambda { |project, options| project.issues_enabled? && project.default_issues_tracker? }
+ expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:user]) && project.default_issues_tracker? }
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
expose :public_builds
expose :shared_with_groups do |project, options|
@@ -211,6 +219,7 @@ module API
expose :user_notes_count
expose :upvotes, :downvotes
expose :due_date
+ expose :confidential
expose :web_url do |issue, options|
Gitlab::UrlBuilder.build(issue)
@@ -232,6 +241,8 @@ module API
expose :milestone, using: Entities::Milestone
expose :merge_when_build_succeeds
expose :merge_status
+ expose :diff_head_sha, as: :sha
+ expose :merge_commit_sha
expose :subscribed do |merge_request, options|
merge_request.subscribed?(options[:current_user])
end
@@ -574,5 +585,10 @@ module API
class Template < Grape::Entity
expose :name, :content
end
+
+ class BroadcastMessage < Grape::Entity
+ expose :id, :message, :starts_at, :ends_at, :color, :font
+ expose :active?, as: :active
+ end
end
end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 9d8b8d737a9..d2df77238d5 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -30,7 +30,7 @@ module API
# Example Request:
# POST /groups
post do
- authorize! :create_group, current_user
+ authorize! :create_group
required_attributes! [:name, :path]
attrs = attributes_for_keys [:name, :path, :description, :visibility_level]
@@ -97,7 +97,7 @@ module API
group = find_group(params[:id])
projects = GroupProjectsFinder.new(group).execute(current_user)
projects = paginate projects
- present projects, with: Entities::Project
+ present projects, with: Entities::Project, user: current_user
end
# Transfer a project to the Group namespace
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index da4b1bf9902..6a20ba95a79 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -129,7 +129,7 @@ module API
forbidden! unless current_user.is_admin?
end
- def authorize!(action, subject)
+ def authorize!(action, subject = nil)
forbidden! unless can?(current_user, action, subject)
end
@@ -148,7 +148,7 @@ module API
end
def can?(object, action, subject)
- abilities.allowed?(object, action, subject)
+ Ability.allowed?(object, action, subject)
end
# Checks the occurrences of required attributes, each attribute must be present in the params hash
@@ -408,14 +408,6 @@ module API
links.join(', ')
end
- def abilities
- @abilities ||= begin
- abilities = Six.new
- abilities << Ability
- abilities
- end
- end
-
def secret_token
File.read(Gitlab.config.gitlab_shell.secret_file).chomp
end
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index 5b54c11ef62..6e6efece7c4 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -105,15 +105,19 @@ module API
post '/two_factor_recovery_codes' do
status 200
- key = Key.find(params[:key_id])
- user = key.user
+ key = Key.find_by(id: params[:key_id])
+
+ unless key
+ return { 'success' => false, 'message' => 'Could not find the given key' }
+ end
- # Make sure this isn't a deploy key
- unless key.type.nil?
+ if key.is_a?(DeployKey)
return { success: false, message: 'Deploy keys cannot be used to retrieve recovery codes' }
end
- unless user.present?
+ user = key.user
+
+ unless user
return { success: false, message: 'Could not find a user for the given key' }
end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 077258faee1..556684187d8 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -140,12 +140,13 @@ module API
# labels (optional) - The labels of an issue
# created_at (optional) - Date time string, ISO 8601 formatted
# due_date (optional) - Date time string in the format YEAR-MONTH-DAY
+ # confidential (optional) - Boolean parameter if the issue should be confidential
# Example Request:
# POST /projects/:id/issues
post ':id/issues' do
required_attributes! [:title]
- keys = [:title, :description, :assignee_id, :milestone_id, :due_date]
+ keys = [:title, :description, :assignee_id, :milestone_id, :due_date, :confidential]
keys << :created_at if current_user.admin? || user_project.owner == current_user
attrs = attributes_for_keys(keys)
@@ -154,21 +155,19 @@ module API
render_api_error!({ labels: errors }, 400)
end
- project = user_project
+ attrs[:labels] = params[:labels] if params[:labels]
- issue = ::Issues::CreateService.new(project, current_user, attrs.merge(request: request, api: true)).execute
+ # Convert and filter out invalid confidential flags
+ attrs['confidential'] = to_boolean(attrs['confidential'])
+ attrs.delete('confidential') if attrs['confidential'].nil?
+
+ issue = ::Issues::CreateService.new(user_project, current_user, attrs.merge(request: request, api: true)).execute
if issue.spam?
render_api_error!({ error: 'Spam detected' }, 400)
end
if issue.valid?
- # Find or create labels and attach to issue. Labels are valid because
- # we already checked its name, so there can't be an error here
- if params[:labels].present?
- issue.add_labels_by_names(params[:labels].split(','))
- end
-
present issue, with: Entities::Issue, current_user: current_user
else
render_validation_error!(issue)
@@ -188,12 +187,13 @@ module API
# state_event (optional) - The state event of an issue (close|reopen)
# updated_at (optional) - Date time string, ISO 8601 formatted
# due_date (optional) - Date time string in the format YEAR-MONTH-DAY
+ # confidential (optional) - Boolean parameter if the issue should be confidential
# Example Request:
# PUT /projects/:id/issues/:issue_id
put ':id/issues/:issue_id' do
issue = user_project.issues.find(params[:issue_id])
authorize! :update_issue, issue
- keys = [:title, :description, :assignee_id, :milestone_id, :state_event, :due_date]
+ keys = [:title, :description, :assignee_id, :milestone_id, :state_event, :due_date, :confidential]
keys << :updated_at if current_user.admin? || user_project.owner == current_user
attrs = attributes_for_keys(keys)
@@ -202,17 +202,15 @@ module API
render_api_error!({ labels: errors }, 400)
end
+ attrs[:labels] = params[:labels] if params[:labels]
+
+ # Convert and filter out invalid confidential flags
+ attrs['confidential'] = to_boolean(attrs['confidential'])
+ attrs.delete('confidential') if attrs['confidential'].nil?
+
issue = ::Issues::UpdateService.new(user_project, current_user, attrs).execute(issue)
if issue.valid?
- # Find or create labels and attach to issue. Labels are valid because
- # we already checked its name, so there can't be an error here
- if params[:labels] && can?(current_user, :admin_issue, user_project)
- issue.remove_labels
- # Create and add labels to the new created issue
- issue.add_labels_by_names(params[:labels].split(','))
- end
-
present issue, with: Entities::Issue, current_user: current_user
else
render_validation_error!(issue)
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 71efd4f33ca..4033f597859 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -51,7 +51,7 @@ module API
@projects = current_user.viewable_starred_projects
@projects = filter_projects(@projects)
@projects = paginate @projects
- present @projects, with: Entities::Project
+ present @projects, with: Entities::Project, user: current_user
end
# Get all projects for admin user
@@ -105,6 +105,7 @@ module API
# visibility_level (optional) - 0 by default
# import_url (optional)
# public_builds (optional)
+ # lfs_enabled (optional)
# Example Request
# POST /projects
post do
@@ -124,7 +125,8 @@ module API
:visibility_level,
:import_url,
:public_builds,
- :only_allow_merge_if_build_succeeds]
+ :only_allow_merge_if_build_succeeds,
+ :lfs_enabled]
attrs = map_public_to_visibility_level(attrs)
@project = ::Projects::CreateService.new(current_user, attrs).execute
if @project.saved?
@@ -156,6 +158,7 @@ module API
# visibility_level (optional)
# import_url (optional)
# public_builds (optional)
+ # lfs_enabled (optional)
# Example Request
# POST /projects/user/:user_id
post "user/:user_id" do
@@ -174,7 +177,8 @@ module API
:visibility_level,
:import_url,
:public_builds,
- :only_allow_merge_if_build_succeeds]
+ :only_allow_merge_if_build_succeeds,
+ :lfs_enabled]
attrs = map_public_to_visibility_level(attrs)
@project = ::Projects::CreateService.new(user, attrs).execute
if @project.saved?
@@ -185,16 +189,30 @@ module API
end
end
- # Fork new project for the current user.
+ # Fork new project for the current user or provided namespace.
#
# Parameters:
# id (required) - The ID of a project
+ # namespace (optional) - The ID or name of the namespace that the project will be forked into.
# Example Request
# POST /projects/fork/:id
post 'fork/:id' do
+ attrs = {}
+ namespace_id = params[:namespace]
+
+ if namespace_id.present?
+ namespace = Namespace.find_by(id: namespace_id) || Namespace.find_by_path_or_name(namespace_id)
+
+ not_found!('Target Namespace') unless namespace
+
+ attrs[:namespace] = namespace
+ end
+
@forked_project =
::Projects::ForkService.new(user_project,
- current_user).execute
+ current_user,
+ attrs).execute
+
if @forked_project.errors.any?
conflict!(@forked_project.errors.messages)
else
@@ -220,6 +238,7 @@ module API
# public (optional) - if true same as setting visibility_level = 20
# visibility_level (optional) - visibility level of a project
# public_builds (optional)
+ # lfs_enabled (optional)
# Example Request
# PUT /projects/:id
put ':id' do
@@ -237,7 +256,8 @@ module API
:public,
:visibility_level,
:public_builds,
- :only_allow_merge_if_build_succeeds]
+ :only_allow_merge_if_build_succeeds,
+ :lfs_enabled]
attrs = map_public_to_visibility_level(attrs)
authorize_admin_project
authorize! :rename_project, user_project if attrs[:name].present?
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 8a376d3c2a3..c440305ff0f 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -327,7 +327,7 @@ module API
# Example Request:
# GET /user
get do
- present @current_user, with: Entities::UserLogin
+ present @current_user, with: Entities::UserFull
end
# Get currently authenticated user's keys