Commit 47c69fd7 authored by Rémy Coutable's avatar Rémy Coutable

Extract EE-specific entities and entity extensions to a separate file

Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent efd27a92
API::API.logger Rails.logger
mount API::API => '/'
::API::API.logger Rails.logger
mount ::API::API => '/'
......@@ -59,7 +59,7 @@ module EE
def render_approvals_json
respond_to do |format|
format.json do
entity = ::API::Entities::MergeRequestApprovals.new(merge_request, current_user: current_user)
entity = EE::API::Entities::MergeRequestApprovals.new(merge_request, current_user: current_user)
render json: entity
end
end
......
class GeoNodeStatusSerializer < BaseSerializer
entity API::Entities::GeoNodeStatus
entity EE::API::Entities::GeoNodeStatus
end
......@@ -54,7 +54,7 @@ module API
# The issues list in the correct order in body will be returned as part of #4250
if result
present epic.issues(current_user),
with: Entities::EpicIssue,
with: EE::API::Entities::EpicIssue,
current_user: current_user
else
render_api_error!({ error: "Issue could not be moved!" }, 400)
......@@ -62,7 +62,7 @@ module API
end
desc 'Get issues assigned to the epic' do
success Entities::EpicIssue
success EE::API::Entities::EpicIssue
end
params do
requires :epic_iid, type: Integer, desc: 'The iid of the epic'
......@@ -71,12 +71,12 @@ module API
authorize_can_read!
present epic.issues(current_user),
with: Entities::EpicIssue,
with: EE::API::Entities::EpicIssue,
current_user: current_user
end
desc 'Assign an issue to the epic' do
success Entities::EpicIssueLink
success EE::API::Entities::EpicIssueLink
end
params do
requires :epic_iid, type: Integer, desc: 'The iid of the epic'
......@@ -93,14 +93,14 @@ module API
if result[:status] == :success
epic_issue_link = EpicIssue.find_by!(epic: epic, issue: issue)
present epic_issue_link, with: Entities::EpicIssueLink
present epic_issue_link, with: EE::API::Entities::EpicIssueLink
else
render_api_error!(result[:message], result[:http_status])
end
end
desc 'Remove an issue from the epic' do
success Entities::EpicIssueLink
success EE::API::Entities::EpicIssueLink
end
params do
requires :epic_iid, type: Integer, desc: 'The iid of the epic'
......@@ -112,7 +112,7 @@ module API
result = ::EpicIssues::DestroyService.new(link, current_user).execute
if result[:status] == :success
present link, with: Entities::EpicIssueLink
present link, with: EE::API::Entities::EpicIssueLink
else
render_api_error!(result[:message], result[:http_status])
end
......
......@@ -46,7 +46,7 @@ module API
resource :groups, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
desc 'Get epics for the group' do
success Entities::Epic
success EE::API::Entities::Epic
end
params do
optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at',
......@@ -58,11 +58,11 @@ module API
optional :labels, type: String, desc: 'Comma-separated list of label names'
end
get ':id/-/epics' do
present find_epics(group_id: user_group.id), with: Entities::Epic
present find_epics(group_id: user_group.id), with: EE::API::Entities::Epic
end
desc 'Get details of an epic' do
success Entities::Epic
success EE::API::Entities::Epic
end
params do
requires :epic_iid, type: Integer, desc: 'The internal ID of an epic'
......@@ -70,11 +70,11 @@ module API
get ':id/-/epics/:epic_iid' do
authorize_can_read!
present epic, with: Entities::Epic
present epic, with: EE::API::Entities::Epic
end
desc 'Create a new epic' do
success Entities::Epic
success EE::API::Entities::Epic
end
params do
requires :title, type: String, desc: 'The title of an epic'
......@@ -88,14 +88,14 @@ module API
epic = ::Epics::CreateService.new(user_group, current_user, declared_params(include_missing: false)).execute
if epic.valid?
present epic, with: Entities::Epic
present epic, with: EE::API::Entities::Epic
else
render_validation_error!(epic)
end
end
desc 'Update an epic' do
success Entities::Epic
success EE::API::Entities::Epic
end
params do
requires :epic_iid, type: Integer, desc: 'The internal ID of an epic'
......@@ -114,14 +114,14 @@ module API
result = ::Epics::UpdateService.new(user_group, current_user, update_params).execute(epic)
if result.valid?
present result, with: Entities::Epic
present result, with: EE::API::Entities::Epic
else
render_validation_error!(result)
end
end
desc 'Destroy an epic' do
success Entities::Epic
success EE::API::Entities::Epic
end
params do
requires :epic_iid, type: Integer, desc: 'The internal ID of an epic'
......
......@@ -36,7 +36,7 @@ module API
authenticate_by_gitlab_geo_node_token!
status = ::GeoNodeStatus.current_node_status
present status, with: Entities::GeoNodeStatus
present status, with: EE::API::Entities::GeoNodeStatus
end
end
......
......@@ -12,13 +12,13 @@ module API
# Example request:
# GET /geo_nodes
desc 'Retrieves the available Geo nodes' do
success Entities::GeoNode
success EE::API::Entities::GeoNode
end
get do
nodes = GeoNode.all
present paginate(nodes), with: Entities::GeoNode
present paginate(nodes), with: EE::API::Entities::GeoNode
end
# Get all Geo node statuses
......@@ -26,12 +26,12 @@ module API
# Example request:
# GET /geo_nodes/status
desc 'Get status for all Geo nodes' do
success Entities::GeoNodeStatus
success EE::API::Entities::GeoNodeStatus
end
get '/status' do
status = GeoNodeStatus.all
present paginate(status), with: Entities::GeoNodeStatus
present paginate(status), with: EE::API::Entities::GeoNodeStatus
end
# Get project registry failures for the current Geo node
......@@ -78,12 +78,12 @@ module API
# Example request:
# GET /geo_nodes/:id
desc 'Get a single GeoNode' do
success Entities::GeoNode
success EE::API::Entities::GeoNode
end
get do
not_found!('GeoNode') unless geo_node
present geo_node, with: Entities::GeoNode
present geo_node, with: EE::API::Entities::GeoNode
end
# Get Geo metrics for a single node
......@@ -91,14 +91,14 @@ module API
# Example request:
# GET /geo_nodes/:id/status
desc 'Get metrics for a single Geo node' do
success Entities::GeoNodeStatus
success EE::API::Entities::GeoNodeStatus
end
get 'status' do
not_found!('GeoNode') unless geo_node
not_found!('Status for Geo node not found') unless geo_node_status
present geo_node_status, with: Entities::GeoNodeStatus
present geo_node_status, with: EE::API::Entities::GeoNodeStatus
end
# Repair authentication of the Geo node
......@@ -106,14 +106,14 @@ module API
# Example request:
# POST /geo_nodes/:id/repair
desc 'Repair authentication of the Geo node' do
success Entities::GeoNodeStatus
success EE::API::Entities::GeoNodeStatus
end
post 'repair' do
not_found!('GeoNode') unless geo_node
if !geo_node.missing_oauth_application? || geo_node.repair
status 200
present geo_node_status, with: Entities::GeoNodeStatus
present geo_node_status, with: EE::API::Entities::GeoNodeStatus
else
render_validation_error!(geo_node)
end
......@@ -124,7 +124,7 @@ module API
# Example request:
# PUT /geo_nodes/:id
desc 'Edit an existing Geo secondary node' do
success Entities::GeoNode
success EE::API::Entities::GeoNode
end
params do
optional :enabled, type: Boolean, desc: 'Flag indicating if the Geo node is enabled'
......@@ -140,7 +140,7 @@ module API
if geo_node.primary?
forbidden!('Primary node cannot be edited')
elsif geo_node.update_attributes(update_params)
present geo_node, with: Entities::GeoNode
present geo_node, with: EE::API::Entities::GeoNode
else
render_validation_error!(geo_node)
end
......
......@@ -10,20 +10,20 @@ module API
end
resource :projects, requirements: { id: %r{[^/]+} } do
desc 'Get related issues' do
success Entities::RelatedIssue
success EE::API::Entities::RelatedIssue
end
get ':id/issues/:issue_iid/links' do
source_issue = find_project_issue(params[:issue_iid])
related_issues = source_issue.related_issues(current_user)
present related_issues,
with: Entities::RelatedIssue,
with: EE::API::Entities::RelatedIssue,
current_user: current_user,
project: user_project
end
desc 'Relate issues' do
success Entities::IssueLink
success EE::API::Entities::IssueLink
end
params do
requires :target_project_id, type: String, desc: 'The ID of the target project'
......@@ -43,14 +43,14 @@ module API
if result[:status] == :success
issue_link = IssueLink.find_by!(source: source_issue, target: target_issue)
present issue_link, with: Entities::IssueLink
present issue_link, with: EE::API::Entities::IssueLink
else
render_api_error!(result[:message], result[:http_status])
end
end
desc 'Remove issues relation' do
success Entities::IssueLink
success EE::API::Entities::IssueLink
end
params do
requires :issue_link_id, type: Integer, desc: 'The ID of an issue link'
......@@ -66,7 +66,7 @@ module API
.execute
if result[:status] == :success
present issue_link, with: Entities::IssueLink
present issue_link, with: EE::API::Entities::IssueLink
else
render_api_error!(result[:message], result[:http_status])
end
......
......@@ -15,7 +15,7 @@ module API
end
desc 'Get a LDAP groups list. Limit size to 20 of them.' do
success Entities::LdapGroup
success EE::API::Entities::LdapGroup
end
params do
use :search_params
......@@ -23,18 +23,18 @@ module API
get 'groups' do
provider = Gitlab::LDAP::Config.available_servers.first['provider_name']
groups = get_group_list(provider, params[:search])
present groups, with: Entities::LdapGroup
present groups, with: EE::API::Entities::LdapGroup
end
desc 'Get a LDAP groups list by the requested provider. Limit size to 20 of them.' do
success Entities::LdapGroup
success EE::API::Entities::LdapGroup
end
params do
use :search_params
end
get ':provider/groups' do
groups = get_group_list(params[:provider], params[:search])
present groups, with: Entities::LdapGroup
present groups, with: EE::API::Entities::LdapGroup
end
end
end
......
......@@ -7,7 +7,7 @@ module API
end
resource :groups do
desc 'Add a linked LDAP group to group' do
success Entities::LdapGroupLink
success EE::API::Entities::LdapGroupLink
end
params do
requires 'cn', type: String, desc: 'The CN of a LDAP group'
......@@ -21,7 +21,7 @@ module API
ldap_group_link = group.ldap_group_links.new(declared_params(include_missing: false))
if ldap_group_link.save
present ldap_group_link, with: Entities::LdapGroupLink
present ldap_group_link, with: EE::API::Entities::LdapGroupLink
else
render_api_error!(ldap_group_link.errors.full_messages.first, 409)
end
......
......@@ -4,16 +4,16 @@ module API
resource :license do
desc 'Get information on the currently active license' do
success Entities::GitlabLicense
success EE::API::Entities::GitlabLicense
end
get do
license = ::License.current
present license, with: Entities::GitlabLicense
present license, with: EE::API::Entities::GitlabLicense
end
desc 'Add a new license' do
success Entities::GitlabLicense
success EE::API::Entities::GitlabLicense
end
params do
requires :license, type: String, desc: 'The license text'
......@@ -21,7 +21,7 @@ module API
post do
license = ::License.new(data: params[:license])
if license.save
present license, with: Entities::GitlabLicense
present license, with: EE::API::Entities::GitlabLicense
else
render_api_error!(license.errors.full_messages.first, 400)
end
......
......@@ -25,15 +25,15 @@ module API
end
desc 'Get project push rule' do
success Entities::ProjectPushRule
success EE::API::Entities::ProjectPushRule
end
get ":id/push_rule" do
push_rule = user_project.push_rule
present push_rule, with: Entities::ProjectPushRule
present push_rule, with: EE::API::Entities::ProjectPushRule
end
desc 'Add a push rule to a project' do
success Entities::ProjectPushRule
success EE::API::Entities::ProjectPushRule
end
params do
use :push_rule_params
......@@ -43,12 +43,12 @@ module API
error!("Project push rule exists", 422)
else
push_rule = user_project.create_push_rule(declared_params(include_missing: false))
present push_rule, with: Entities::ProjectPushRule
present push_rule, with: EE::API::Entities::ProjectPushRule
end
end
desc 'Update an existing project push rule' do
success Entities::ProjectPushRule
success EE::API::Entities::ProjectPushRule
end
params do
use :push_rule_params
......@@ -58,7 +58,7 @@ module API
not_found!('Push Rule') unless push_rule
if push_rule.update_attributes(declared_params(include_missing: false))
present push_rule, with: Entities::ProjectPushRule
present push_rule, with: EE::API::Entities::ProjectPushRule
else
render_validation_error!(push_rule)
end
......
......@@ -20,16 +20,16 @@ module API
end
desc 'Get project push rule' do
success ::API::Entities::ProjectPushRule
success EE::API::Entities::ProjectPushRule
detail DEPRECATION_MESSAGE
end
get ":id/git_hook" do
push_rule = user_project.push_rule
present push_rule, with: ::API::Entities::ProjectPushRule
present push_rule, with: EE::API::Entities::ProjectPushRule
end
desc 'Add a push rule to a project' do
success ::API::Entities::ProjectPushRule
success EE::API::Entities::ProjectPushRule
detail DEPRECATION_MESSAGE
end
params do
......@@ -40,12 +40,12 @@ module API
error!("Project push rule exists", 422)
else
push_rule = user_project.create_push_rule(declared_params)
present push_rule, with: ::API::Entities::ProjectPushRule
present push_rule, with: EE::API::Entities::ProjectPushRule
end
end
desc 'Update an existing project push rule' do
success ::API::Entities::ProjectPushRule
success EE::API::Entities::ProjectPushRule
detail DEPRECATION_MESSAGE
end
params do
......@@ -56,7 +56,7 @@ module API
not_found!('Push Rule') unless push_rule
if push_rule.update_attributes(declared_params(include_missing: false))
present push_rule, with: ::API::Entities::ProjectPushRule
present push_rule, with: EE::API::Entities::ProjectPushRule
else
render_validation_error!(push_rule)
end
......
module EE
module API
module Entities
#######################
# Entities extensions #
#######################
module UserPublic
extend ActiveSupport::Concern
prepended do
expose :shared_runners_minutes_limit
end
end
module Project
extend ActiveSupport::Concern
prepended do
expose :repository_storage, if: ->(_project, options) { options[:current_user].try(:admin?) }
expose :approvals_before_merge, if: ->(project, _) { project.feature_available?(:merge_request_approvers) }
end
end
module Group
extend ActiveSupport::Concern
prepended do
expose :ldap_cn, :ldap_access
expose :ldap_group_links,
using: EE::API::Entities::LdapGroupLink,
if: ->(group, options) { group.ldap_group_links.any? }
end
end
module GroupDetail
extend ActiveSupport::Concern
prepended do
expose :shared_runners_minutes_limit
end
end
module ProtectedRefAccess
extend ActiveSupport::Concern
prepended do
expose :user_id
expose :group_id
end
end
module IssueBasic
extend ActiveSupport::Concern
prepended do
expose :weight, if: ->(issue, _) { issue.supports_weight? }
end
end
module MergeRequestBasic
extend ActiveSupport::Concern
prepended do
expose :approvals_before_merge
expose :squash, if: ->(mr, _) { mr.project.feature_available?(:merge_request_squash) }
end
end
module Namespace
extend ActiveSupport::Concern
prepended do
expose :shared_runners_minutes_limit, if: ->(_, options) { options[:current_user]&.admin? }
expose :plan, if: ->(namespace, opts) { ::Ability.allowed?(opts[:current_user], :admin_namespace, namespace) } do |namespace, _|
namespace.plan&.name
end
end
end
module Board
extend ActiveSupport::Concern
prepended do
def scoped_issue_available?(board)
board.parent.feature_available?(:scoped_issue_board)
end
# Default filtering configuration
expose :name
expose :group
expose :milestone, using: ::API::Entities::Milestone, if: ->(board, _) { scoped_issue_available?(board) }
expose :assignee, using: ::API::Entities::UserBasic, if: ->(board, _) { scoped_issue_available?(board) }
expose :labels, using: ::API::Entities::LabelBasic, if: ->(board, _) { scoped_issue_available?(board) }
expose :weight, if: ->(board, _) { scoped_issue_available?(board) }
end
end
module ApplicationSetting
extend ActiveSupport::Concern
prepended do
expose(*EE::ApplicationSettingsHelper.repository_mirror_attributes, if: ->(_instance, _options) do
::License.feature_available?(:repository_mirrors)
end)
expose(*EE::ApplicationSettingsHelper.external_authorization_service_attributes, if: ->(_instance, _options) do
::License.feature_available?(:external_authorization_service)
end)
end
end
module Variable
extend ActiveSupport::Concern
prepended do
expose :environment_scope, if: ->(variable, options) do
if variable.respond_to?(:environment_scope)
variable.project.feature_available?(:variable_environment_scope)
end
end
end
end
########################
# EE-specific entities #
########################
class ProjectPushRule < Grape::Entity
expose :id, :project_id, :created_at
expose :commit_message_regex, :branch_name_regex, :deny_delete_tag
expose :member_check, :prevent_secrets, :author_email_regex
expose :file_name_regex, :max_file_size
end
class LdapGroupLink < Grape::Entity
expose :cn, :group_access, :provider
end
class RelatedIssue < ::API::Entities::Issue
expose :issue_link_id
end
class Epic < Grape::Entity
expose :id
expose :iid
expose :group_id
expose :title
expose :description
expose :author, using: ::API::Entities::UserBasic
expose :start_date
expose :end_date
expose :created_at
expose :updated_at
expose :labels do |epic, options|
# Avoids an N+1 query since labels are preloaded
epic.labels.map(&:title).sort
end
end
class EpicIssue < ::API::Entities::Issue
expose :epic_issue_id
expose :relative_position
end
class EpicIssueLink < Grape::Entity
expose :id
expose :relative_position
expose :epic, using: EE::API::Entities::Epic
expose :issue, using: ::API::Entities::IssueBasic
end
class IssueLink < Grape::Entity
expose :source, as: :source_issue, using: ::API::Entities::IssueBasic
expose :target, as: :target_issue, using: ::API::Entities::IssueBasic
end
class Approvals < Grape::Entity
expose :user, using: ::API::Entities::UserBasic
end
class MergeRequestApprovals < ::API::Entities::ProjectEntity
expose :merge_status
expose :approvals_required
expose :approvals_left
expose :approvals, as: :approved_by, using: EE::API::Entities::Approvals
expose :approvers_left, as: :suggested_approvers, using: ::API::Entities::UserBasic
expose :user_has_approved do |merge_request, options|
merge_request.has_approved?(options[:current_user])
end
expose :user_can_approve do |merge_request, options|
merge_request.can_approve?(options[:current_user])
end
end
class LdapGroup < Grape::Entity
expose :cn
end
class GitlabLicense < Grape::Entity
expose :starts_at, :expires_at, :licensee, :add_ons
expose :user_limit do |license, options|
license.restricted?(:active_user_count) ? license.restrictions[:active_user_count] : 0
end
expose :active_users do |license, options|
::User.active.count
end
end
class GeoNode < Grape::Entity
include ::API::Helpers::RelatedResourcesHelpers
expose :id
expose :url
expose :primary?, as: :primary
expose :enabled
expose :current?, as: :current
expose :files_max_capacity
expose :repos_max_capacity
# Retained for backwards compatibility. Remove in API v5
expose :clone_protocol do |_record, _options|
'http'
end
expose :_links do
expose :self do |geo_node|
expose_url api_v4_geo_nodes_path(id: geo_node.id)
end
expose :repair do |geo_node|
expose_url api_v4_geo_nodes_repair_path(id: geo_node.id)
end
end
end
class GeoNodeStatus < Grape::Entity
include ::API::Helpers::RelatedResourcesHelpers
include ActionView::Helpers::NumberHelper
expose :geo_node_id
expose :healthy?, as: :healthy
expose :health do |node|
node.healthy? ? 'Healthy' : node.health
end
expose :health_status
expose :missing_oauth_application
expose :attachments_count
expose :attachments_synced_count
expose :attachments_failed_count
expose :attachments_synced_in_percentage do |node|
number_to_percentage(node.attachments_synced_in_percentage, precision: 2)
end
expose :db_replication_lag_seconds
expose :lfs_objects_count
expose :lfs_objects_synced_count
expose :lfs_objects_failed_count
expose :lfs_objects_synced_in_percentage do |node|
number_to_percentage(node.lfs_objects_synced_in_percentage, precision: 2)
end
expose :job_artifacts_count
expose :job_artifacts_synced_count
expose :job_artifacts_failed_count
expose :job_artifacts_synced_in_percentage do |node|
number_to_percentage(node.job_artifacts_synced_in_percentage, precision: 2)
end
expose :repositories_count
expose :repositories_failed_count
expose :repositories_synced_count
expose :repositories_synced_in_percentage do |node|
number_to_percentage(node.repositories_synced_in_percentage, precision: 2)
end
expose :wikis_count
expose :wikis_failed_count
expose :wikis_synced_count
expose :wikis_synced_in_percentage do |node|
number_to_percentage(node.wikis_synced_in_percentage, precision: 2)
end
expose :replication_slots_count
expose :replication_slots_used_count
expose :replication_slots_used_in_percentage do |node|
number_to_percentage(node.replication_slots_used_in_percentage, precision: 2)
end
expose :replication_slots_max_retained_wal_bytes
expose :last_event_id
expose :last_event_timestamp
expose :cursor_last_event_id
expose :cursor_last_event_timestamp
expose :last_successful_status_check_timestamp
expose :version
expose :revision
expose :selective_sync_type
# Deprecated: remove in API v5. We use selective_sync_type instead now.
expose :namespaces, using: ::API::Entities::NamespaceBasic
expose :updated_at
# We load GeoNodeStatus data in two ways:
#
# 1. Directly by asking a Geo node via an API call
# 2. Via cached state in the database
#
# We don't yet cached the state of the shard information in the database, so if
# we don't have this information omit from the serialization entirely.
expose :storage_shards, using: StorageShardEntity, if: ->(status, options) do
status.storage_shards.present?
end
expose :storage_shards_match?, as: :storage_shards_match, if: ->(status, options) do
::Gitlab::Geo.primary? && status.storage_shards.present?
end
expose :_links do
expose :self do |geo_node_status|
expose_url api_v4_geo_nodes_status_path(id: geo_node_status.geo_node_id)
end
expose :node do |geo_node_status|
expose_url api_v4_geo_nodes_path(id: geo_node_status.geo_node_id)
end
end
private
def namespaces
object.geo_node.namespaces
end
def missing_oauth_application
object.geo_node.missing_oauth_application?
end
end
end
end
end
require 'spec_helper'
describe API::Entities::GeoNodeStatus, :postgresql do
describe EE::API::Entities::GeoNodeStatus, :postgresql do
include ::EE::GeoHelpers
let(:geo_node_status) { build(:geo_node_status) }
......
......@@ -55,9 +55,6 @@ module API
expose :can_create_project?, as: :can_create_project
expose :two_factor_enabled?, as: :two_factor_enabled
expose :external
# EE-only
expose :shared_runners_minutes_limit
end
class UserWithAdmin < UserPublic
......@@ -79,13 +76,6 @@ module API
expose :job_events
end
class ProjectPushRule < Grape::Entity
expose :id, :project_id, :created_at
expose :commit_message_regex, :branch_name_regex, :deny_delete_tag
expose :member_check, :prevent_secrets, :author_email_regex
expose :file_name_regex, :max_file_size
end
class SharedGroup < Grape::Entity
expose :group_id
expose :group_name do |group_link, options|
......@@ -198,14 +188,10 @@ module API
SharedGroup.represent(project.project_group_links, options)
end
expose :only_allow_merge_if_pipeline_succeeds
expose :repository_storage, if: lambda { |_project, options| options[:current_user].try(:admin?) }
expose :request_access_enabled
expose :only_allow_merge_if_all_discussions_are_resolved
expose :printing_merge_request_link_enabled
# EE only
expose :approvals_before_merge, if: ->(project, _) { project.feature_available?(:merge_request_approvers) }
expose :statistics, using: 'API::Entities::ProjectStatistics', if: :statistics
def self.preload_relation(projects_relation, options = {})
......@@ -240,20 +226,9 @@ module API
expose :requested_at
end
class LdapGroupLink < Grape::Entity
expose :cn, :group_access, :provider
end
class Group < Grape::Entity
expose :id, :name, :path, :description, :visibility
## EE-only
expose :ldap_cn, :ldap_access
expose :ldap_group_links,
using: Entities::LdapGroupLink,
if: lambda { |group, options| group.ldap_group_links.any? }
## EE-only
expose :lfs_enabled?, as: :lfs_enabled
expose :avatar_url do |group, options|
group.avatar_url(only_path: false)
......@@ -294,9 +269,6 @@ module API
options: { only_shared: true }
).execute
end
# EE-only
expose :shared_runners_minutes_limit
end
class Commit < Grape::Entity
......@@ -397,11 +369,6 @@ module API
class ProtectedRefAccess < Grape::Entity
expose :access_level
## EE-only
expose :user_id
expose :group_id
## EE-only
expose :access_level_description do |protected_ref_access|
protected_ref_access.humanize
end
......@@ -455,7 +422,6 @@ module API
end
expose :due_date
expose :confidential
expose :weight, if: ->(issue, _) { issue.supports_weight? }
expose :discussion_locked
expose :web_url do |issue, options|
......@@ -493,44 +459,6 @@ module API
end
end
class RelatedIssue < Issue
expose :issue_link_id
end
class Epic < Grape::Entity
expose :id
expose :iid
expose :group_id
expose :title
expose :description
expose :author, using: Entities::UserBasic
expose :start_date
expose :end_date
expose :created_at
expose :updated_at
expose :labels do |epic, options|
# Avoids an N+1 query since labels are preloaded
epic.labels.map(&:title).sort
end
end
class EpicIssue < Issue
expose :epic_issue_id
expose :relative_position
end
class EpicIssueLink < Grape::Entity
expose :id
expose :relative_position
expose :epic, using: Entities::Epic
expose :issue, using: Entities::IssueBasic
end
class IssueLink < Grape::Entity
expose :source, as: :source_issue, using: Entities::IssueBasic
expose :target, as: :target_issue, using: Entities::IssueBasic
end
class IssuableTimeStats < Grape::Entity
format_with(:time_tracking_formatter) do |time_spent|
Gitlab::TimeTrackingFormatter.output(time_spent)
......@@ -599,13 +527,10 @@ module API
expose :diff_head_sha, as: :sha
expose :merge_commit_sha
expose :user_notes_count
expose :approvals_before_merge
expose :discussion_locked
expose :should_remove_source_branch?, as: :should_remove_source_branch
expose :force_remove_source_branch?, as: :force_remove_source_branch
expose :squash, if: -> (mr, _) { mr.project.feature_available?(:merge_request_squash) }
expose :web_url do |merge_request, options|
Gitlab::UrlBuilder.build(merge_request)
end
......@@ -631,26 +556,6 @@ module API
end
end
class Approvals < Grape::Entity
expose :user, using: Entities::UserBasic
end
class MergeRequestApprovals < ProjectEntity
expose :merge_status
expose :approvals_required
expose :approvals_left
expose :approvals, as: :approved_by, using: Entities::Approvals
expose :approvers_left, as: :suggested_approvers, using: Entities::UserBasic
expose :user_has_approved do |merge_request, options|
merge_request.has_approved?(options[:current_user])
end
expose :user_can_approve do |merge_request, options|
merge_request.can_approve?(options[:current_user])
end
end
class MergeRequestDiff < Grape::Entity
expose :id, :head_commit_sha, :base_commit_sha, :start_commit_sha,
:created_at, :merge_request_id, :state, :real_size
......@@ -748,10 +653,6 @@ module API
end
end
class LdapGroup < Grape::Entity
expose :cn
end
class ProjectGroupLink < Grape::Entity
expose :id, :project_id, :group_id, :group_access, :expires_at
end
......@@ -794,12 +695,6 @@ module API
def expose_members_count_with_descendants?(namespace, opts)
namespace.kind == 'group' && Ability.allowed?(opts[:current_user], :admin_group, namespace)
end
# EE-only
expose :shared_runners_minutes_limit, if: lambda { |_, options| options[:current_user]&.admin? }
expose :plan, if: -> (namespace, opts) { Ability.allowed?(opts[:current_user], :admin_namespace, namespace) } do |namespace, _|
namespace.plan&.name
end
end
class MemberAccess < Grape::Entity
......@@ -919,20 +814,6 @@ module API
expose :lists, using: Entities::List do |board|
board.lists.destroyable
end
# EE-specific START
def scoped_issue_available?(board)
board.parent.feature_available?(:scoped_issue_board)
end
# Default filtering configuration
expose :name
expose :group
expose :milestone, using: Entities::Milestone, if: -> (board, _) { scoped_issue_available?(board) }
expose :assignee, using: Entities::UserBasic, if: -> (board, _) { scoped_issue_available?(board) }
expose :labels, using: Entities::LabelBasic, if: -> (board, _) { scoped_issue_available?(board) }
expose :weight, if: -> (board, _) { scoped_issue_available?(board) }
# EE-specific END
end
class Compare < Grape::Entity
......@@ -966,13 +847,6 @@ module API
class ApplicationSetting < Grape::Entity
expose :id
expose(*::ApplicationSettingsHelper.visible_attributes)
expose(*EE::ApplicationSettingsHelper.repository_mirror_attributes, if: lambda do |_instance, _options|
::License.feature_available?(:repository_mirrors)
end)
expose(*EE::ApplicationSettingsHelper.external_authorization_service_attributes, if: lambda do |_instance, _options|
::License.feature_available?(:external_authorization_service)
end)
expose(:restricted_visibility_levels) do |setting, _options|
setting.restricted_visibility_levels.map { |level| Gitlab::VisibilityLevel.string_level(level) }
end
......@@ -1002,22 +876,6 @@ module API
end
end
class GitlabLicense < Grape::Entity
expose :starts_at, :expires_at, :licensee, :add_ons
expose :user_limit do |license, options|
license.restricted?(:active_user_count) ? license.restrictions[:active_user_count] : 0
end
expose :active_users do |license, options|
::User.active.count
end
end
class TriggerRequest < Grape::Entity
expose :id, :variables
end
class Runner < Grape::Entity
expose :id
expose :description
......@@ -1085,13 +943,6 @@ module API
class Variable < Grape::Entity
expose :key, :value
expose :protected?, as: :protected, if: -> (entity, _) { entity.respond_to?(:protected?) }
# EE
expose :environment_scope, if: ->(variable, options) {
if variable.respond_to?(:environment_scope)
variable.project.feature_available?(:variable_environment_scope)
end
}
end
class Pipeline < PipelineBasic
......@@ -1155,143 +1006,6 @@ module API
expose :active?, as: :active
end
class GeoNode < Grape::Entity
include ::API::Helpers::RelatedResourcesHelpers
expose :id
expose :url
expose :primary?, as: :primary
expose :enabled
expose :current?, as: :current
expose :files_max_capacity
expose :repos_max_capacity
# Retained for backwards compatibility. Remove in API v5
expose :clone_protocol do |_record, _options|
'http'
end
expose :_links do
expose :self do |geo_node|
expose_url api_v4_geo_nodes_path(id: geo_node.id)
end
expose :repair do |geo_node|
expose_url api_v4_geo_nodes_repair_path(id: geo_node.id)
end
end
end
class GeoNodeStatus < Grape::Entity
include ::API::Helpers::RelatedResourcesHelpers
include ActionView::Helpers::NumberHelper
expose :geo_node_id
expose :healthy?, as: :healthy
expose :health do |node|
node.healthy? ? 'Healthy' : node.health
end
expose :health_status
expose :missing_oauth_application
expose :attachments_count
expose :attachments_synced_count
expose :attachments_failed_count
expose :attachments_synced_in_percentage do |node|
number_to_percentage(node.attachments_synced_in_percentage, precision: 2)
end
expose :db_replication_lag_seconds
expose :lfs_objects_count
expose :lfs_objects_synced_count
expose :lfs_objects_failed_count
expose :lfs_objects_synced_in_percentage do |node|
number_to_percentage(node.lfs_objects_synced_in_percentage, precision: 2)
end
expose :job_artifacts_count
expose :job_artifacts_synced_count
expose :job_artifacts_failed_count
expose :job_artifacts_synced_in_percentage do |node|
number_to_percentage(node.job_artifacts_synced_in_percentage, precision: 2)
end
expose :repositories_count
expose :repositories_failed_count
expose :repositories_synced_count
expose :repositories_synced_in_percentage do |node|
number_to_percentage(node.repositories_synced_in_percentage, precision: 2)
end
expose :wikis_count
expose :wikis_failed_count
expose :wikis_synced_count
expose :wikis_synced_in_percentage do |node|
number_to_percentage(node.wikis_synced_in_percentage, precision: 2)
end
expose :replication_slots_count
expose :replication_slots_used_count
expose :replication_slots_used_in_percentage do |node|
number_to_percentage(node.replication_slots_used_in_percentage, precision: 2)
end
expose :replication_slots_max_retained_wal_bytes
expose :last_event_id
expose :last_event_timestamp
expose :cursor_last_event_id
expose :cursor_last_event_timestamp
expose :last_successful_status_check_timestamp
expose :version
expose :revision
expose :selective_sync_type
# Deprecated: remove in API v5. We use selective_sync_type instead now.
expose :namespaces, using: NamespaceBasic
expose :updated_at
# We load GeoNodeStatus data in two ways:
#
# 1. Directly by asking a Geo node via an API call
# 2. Via cached state in the database
#
# We don't yet cached the state of the shard information in the database, so if
# we don't have this information omit from the serialization entirely.
expose :storage_shards, using: StorageShardEntity, if: ->(status, options) do
status.storage_shards.present?
end
expose :storage_shards_match?, as: :storage_shards_match, if: -> (status, options) do
Gitlab::Geo.primary? && status.storage_shards.present?
end
expose :_links do
expose :self do |geo_node_status|
expose_url api_v4_geo_nodes_status_path(id: geo_node_status.geo_node_id)
end
expose :node do |geo_node_status|
expose_url api_v4_geo_nodes_path(id: geo_node_status.geo_node_id)
end
end
private
def namespaces
object.geo_node.namespaces
end
def missing_oauth_application
object.geo_node.missing_oauth_application?
end
end
class PersonalAccessToken < Grape::Entity
expose :id, :name, :revoked, :created_at, :scopes
expose :active?, as: :active
......@@ -1487,5 +1201,26 @@ module API
expose :startline
expose :project_id
end
def self.prepend_entity(klass, with: nil)
if with.nil?
raise ArgumentError, 'You need to pass either the :with or :namespace option!'
end
klass.descendants.each { |descendant| descendant.prepend(with) }
klass.prepend(with)
end
end
end
API::Entities.prepend_entity(::API::Entities::ApplicationSetting, with: EE::API::Entities::ApplicationSetting)
API::Entities.prepend_entity(::API::Entities::Board, with: EE::API::Entities::Board)
API::Entities.prepend_entity(::API::Entities::Group, with: EE::API::Entities::Group)
API::Entities.prepend_entity(::API::Entities::GroupDetail, with: EE::API::Entities::GroupDetail)
API::Entities.prepend_entity(::API::Entities::IssueBasic, with: EE::API::Entities::IssueBasic)
API::Entities.prepend_entity(::API::Entities::MergeRequestBasic, with: EE::API::Entities::MergeRequestBasic)
API::Entities.prepend_entity(::API::Entities::Namespace, with: EE::API::Entities::Namespace)
API::Entities.prepend_entity(::API::Entities::Project, with: EE::API::Entities::Project)
API::Entities.prepend_entity(::API::Entities::ProtectedRefAccess, with: EE::API::Entities::ProtectedRefAccess)
API::Entities.prepend_entity(::API::Entities::UserPublic, with: EE::API::Entities::UserPublic)
API::Entities.prepend_entity(::API::Entities::Variable, with: EE::API::Entities::Variable)
......@@ -368,12 +368,12 @@ module API
# GET /projects/:id/merge_requests/:merge_request_iid/approvals
#
desc "List a merge request's approvals" do
success Entities::MergeRequestApprovals
success EE::API::Entities::MergeRequestApprovals
end
get ':id/merge_requests/:merge_request_iid/approvals' do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
present merge_request, with: Entities::MergeRequestApprovals, current_user: current_user
present merge_request, with: EE::API::Entities::MergeRequestApprovals, current_user: current_user
end
# Approve a merge request
......@@ -385,7 +385,7 @@ module API
# POST /projects/:id/merge_requests/:merge_request_iid/approve
#
desc 'Approve a merge request' do
success Entities::MergeRequestApprovals
success EE::API::Entities::MergeRequestApprovals
end
params do
optional :sha, type: String, desc: 'When present, must have the HEAD SHA of the source branch'
......@@ -401,11 +401,11 @@ module API
.new(user_project, current_user)
.execute(merge_request)
present merge_request, with: Entities::MergeRequestApprovals, current_user: current_user
present merge_request, with: EE::API::Entities::MergeRequestApprovals, current_user: current_user
end
desc 'Remove an approval from a merge request' do
success Entities::MergeRequestApprovals
success EE::API::Entities::MergeRequestApprovals
end
post ':id/merge_requests/:merge_request_iid/unapprove' do
merge_request = find_project_merge_request(params[:merge_request_iid])
......@@ -416,7 +416,7 @@ module API
.new(user_project, current_user)
.execute(merge_request)
present merge_request, with: Entities::MergeRequestApprovals, current_user: current_user
present merge_request, with: EE::API::Entities::MergeRequestApprovals, current_user: current_user
end
desc 'List issues that will be closed on merge' do
......
......@@ -79,13 +79,13 @@ module API
expose :lfs_enabled?, as: :lfs_enabled
expose :creator_id
expose :namespace, using: 'API::Entities::Namespace'
expose :forked_from_project, using: ::API::Entities::BasicProjectDetails, if: lambda { |project, options| project.forked? }
expose :forked_from_project, using: ::API::Entities::BasicProjectDetails, if: ->(project, options) { project.forked? }
expose :avatar_url do |user, options|
user.avatar_url(only_path: false)
end
expose :star_count, :forks_count
expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:current_user]) && project.default_issues_tracker? }
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
expose :open_issues_count, if: ->(project, options) { project.feature_available?(:issues, options[:current_user]) && project.default_issues_tracker? }
expose :runners_token, if: ->(_project, options) { options[:user_can_admin_project] }
expose :public_builds
expose :shared_with_groups do |project, options|
::API::Entities::SharedGroup.represent(project.project_group_links.all, options)
......@@ -149,13 +149,6 @@ module API
class Group < Grape::Entity
expose :id, :name, :path, :description, :visibility_level
# EE-only
expose :ldap_cn, :ldap_access
expose :ldap_group_links,
using: ::API::Entities::LdapGroupLink,
if: lambda { |group, options| group.ldap_group_links.any? }
# EE-only
expose :lfs_enabled?, as: :lfs_enabled
expose :avatar_url do |user, options|
user.avatar_url(only_path: false)
......@@ -302,7 +295,6 @@ module API
expose :upvotes, :downvotes
expose :due_date
expose :confidential
expose :weight, if: ->(issue, _) { issue.supports_weight? }
expose :web_url do |issue, options|
Gitlab::UrlBuilder.build(issue)
......@@ -321,3 +313,6 @@ module API
end
end
end
API::Entities.prepend_entity(::API::V3::Entities::Group, with: EE::API::Entities::Group)
API::Entities.prepend_entity(::API::V3::Entities::IssueBasic, with: EE::API::Entities::IssueBasic)
......@@ -312,7 +312,7 @@ module API
merge_request = user_project.merge_requests.find(params[:merge_request_id])
authorize! :read_merge_request, merge_request
present merge_request, with: ::API::Entities::MergeRequestApprovals, current_user: current_user
present merge_request, with: EE::API::Entities::MergeRequestApprovals, current_user: current_user
end
# Approve a merge request
......@@ -332,7 +332,7 @@ module API
.new(user_project, current_user)
.execute(merge_request)
present merge_request, with: ::API::Entities::MergeRequestApprovals, current_user: current_user
present merge_request, with: EE::API::Entities::MergeRequestApprovals, current_user: current_user
end
delete "#{path}/unapprove" do
......@@ -344,7 +344,7 @@ module API
.new(user_project, current_user)
.execute(merge_request)
present merge_request, with: ::API::Entities::MergeRequestApprovals, current_user: current_user
present merge_request, with: EE::API::Entities::MergeRequestApprovals, current_user: current_user
end
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment