entities.rb 46.3 KB
Newer Older
1 2
# frozen_string_literal: true

3
module API
N
Nihad Abbasov 已提交
4
  module Entities
B
blackst0ne 已提交
5 6 7 8 9 10 11 12 13 14
    class WikiPageBasic < Grape::Entity
      expose :format
      expose :slug
      expose :title
    end

    class WikiPage < WikiPageBasic
      expose :content
    end

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
    class WikiAttachment < Grape::Entity
      include Gitlab::FileMarkdownLinkBuilder

      expose :file_name
      expose :file_path
      expose :branch
      expose :link do
        expose :file_path, as: :url
        expose :markdown do |_entity|
          self.markdown_link
        end
      end

      def filename
        object.file_name
      end

      def secure_url
        object.file_path
      end
    end

37
    class UserSafe < Grape::Entity
38
      expose :id, :name, :username
39
    end
40

41
    class UserBasic < UserSafe
42
      expose :state
43

44 45 46
      expose :avatar_url do |user, options|
        user.avatar_url(only_path: false)
      end
D
Douwe Maan 已提交
47

48
      expose :avatar_path, if: ->(user, options) { options.fetch(:only_path, false) && user.avatar_path }
49
      expose :custom_attributes, using: 'API::Entities::CustomAttribute', if: :with_custom_attributes
50

D
Douwe Maan 已提交
51
      expose :web_url do |user, options|
52
        Gitlab::Routing.url_helpers.user_url(user)
D
Douwe Maan 已提交
53
      end
N
Nihad Abbasov 已提交
54
    end
N
Nihad Abbasov 已提交
55

56
    class User < UserBasic
57
      expose :created_at, if: ->(user, opts) { Ability.allowed?(opts[:current_user], :read_user_profile, user) }
58
      expose :bio, :location, :public_email, :skype, :linkedin, :twitter, :website_url, :organization
59 60
    end

61 62
    class UserActivity < Grape::Entity
      expose :username
63 64
      expose :last_activity_on
      expose :last_activity_on, as: :last_activity_at # Back-compat
65 66
    end

67 68 69 70
    class Identity < Grape::Entity
      expose :provider, :extern_uid
    end

71
    class UserPublic < User
72 73
      expose :last_sign_in_at
      expose :confirmed_at
74
      expose :last_activity_on
75
      expose :email
76
      expose :theme_id, :color_scheme_id, :projects_limit, :current_sign_in_at
77
      expose :identities, using: Entities::Identity
78 79
      expose :can_create_group?, as: :can_create_group
      expose :can_create_project?, as: :can_create_project
80
      expose :two_factor_enabled?, as: :two_factor_enabled
81
      expose :external
82
      expose :private_profile
83 84
    end

85
    class UserWithAdmin < UserPublic
86
      expose :admin?, as: :is_admin
87 88
    end

B
Bob Van Landuyt 已提交
89 90 91
    class UserStatus < Grape::Entity
      expose :emoji
      expose :message
92 93 94
      expose :message_html do |entity|
        MarkupHelper.markdown_field(entity, :message)
      end
B
Bob Van Landuyt 已提交
95 96
    end

97 98 99 100
    class Email < Grape::Entity
      expose :id, :email
    end

M
miks 已提交
101
    class Hook < Grape::Entity
102
      expose :id, :url, :created_at, :push_events, :tag_push_events, :merge_requests_events, :repository_update_events
103
      expose :enable_ssl_verification
M
miks 已提交
104 105
    end

106
    class ProjectHook < Hook
107
      expose :project_id, :issues_events, :confidential_issues_events
108
      expose :note_events, :confidential_note_events, :pipeline_events, :wiki_page_events
109
      expose :job_events
D
Duana Saskia 已提交
110
      expose :push_events_branch_filter
111 112
    end

113 114 115 116 117 118
    class SharedGroup < Grape::Entity
      expose :group_id
      expose :group_name do |group_link, options|
        group_link.group.name
      end
      expose :group_access, as: :group_access_level
119
      expose :expires_at
120 121
    end

T
Tomasz Maczukin 已提交
122 123
    class ProjectIdentity < Grape::Entity
      expose :id, :description
124 125
      expose :name, :name_with_namespace
      expose :path, :path_with_namespace
T
Tomasz Maczukin 已提交
126 127 128
      expose :created_at
    end

T
Travis Miller 已提交
129 130 131 132
    class ProjectExportStatus < ProjectIdentity
      include ::API::Helpers::RelatedResourcesHelpers

      expose :export_status
133
      expose :_links, if: lambda { |project, _options| project.export_status == :finished } do
T
Travis Miller 已提交
134 135 136 137 138 139 140 141 142 143
        expose :api_url do |project|
          expose_url(api_v4_projects_export_download_path(id: project.id))
        end

        expose :web_url do |project|
          Gitlab::Routing.url_helpers.download_export_project_url(project)
        end
      end
    end

J
James Lopez 已提交
144 145
    class ProjectImportStatus < ProjectIdentity
      expose :import_status
J
James Lopez 已提交
146 147 148

      # TODO: Use `expose_nil` once we upgrade the grape-entity gem
      expose :import_error, if: lambda { |status, _ops| status.import_error }
J
James Lopez 已提交
149 150
    end

F
Francisco Lopez 已提交
151
    class BasicProjectDetails < ProjectIdentity
F
Francisco Lopez 已提交
152 153 154 155 156 157 158 159 160 161 162
      include ::API::ProjectsRelationBuilder

      expose :default_branch
      # Avoids an N+1 query: https://github.com/mbleigh/acts-as-taggable-on/issues/91#issuecomment-168273770
      expose :tag_list do |project|
        # project.tags.order(:name).pluck(:name) is the most suitable option
        # to avoid loading all the ActiveRecord objects but, if we use it here
        # it override the preloaded associations and makes a query
        # (fixed in https://github.com/rails/rails/pull/25976).
        project.tags.map(&:name).sort
      end
J
J.D. Bean 已提交
163

I
Imre Farkas 已提交
164
      expose :ssh_url_to_repo, :http_url_to_repo, :web_url, :readme_url
J
J.D. Bean 已提交
165 166 167 168 169 170 171 172 173 174 175 176 177

      expose :license_url, if: :license do |project|
        license = project.repository.license_blob

        if license
          Gitlab::Routing.url_helpers.project_blob_url(project, File.join(project.default_branch, license.path))
        end
      end

      expose :license, with: 'API::Entities::LicenseBasic', if: :license do |project|
        project.repository.license
      end

178 179 180
      expose :avatar_url do |project, options|
        project.avatar_url(only_path: false)
      end
J
J.D. Bean 已提交
181

182
      expose :star_count, :forks_count
F
Francisco Lopez 已提交
183
      expose :last_activity_at
184
      expose :namespace, using: 'API::Entities::NamespaceBasic'
185 186
      expose :custom_attributes, using: 'API::Entities::CustomAttribute', if: :with_custom_attributes

187
      # rubocop: disable CodeReuse/ActiveRecord
188
      def self.preload_relation(projects_relation, options =  {})
189 190 191 192
        # Preloading tags, should be done with using only `:tags`,
        # as `:tags` are defined as: `has_many :tags, through: :taggings`
        # N+1 is solved then by using `subject.tags.map(&:name)`
        # MR describing the solution: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20555
193
        projects_relation.preload(:project_feature, :route)
194 195
                         .preload(:import_state, :tags)
                         .preload(namespace: [:route, :owner])
196
      end
197
      # rubocop: enable CodeReuse/ActiveRecord
198 199
    end

200
    class Project < BasicProjectDetails
201 202 203 204 205 206 207
      include ::API::Helpers::RelatedResourcesHelpers

      expose :_links do
        expose :self do |project|
          expose_url(api_v4_projects_path(id: project.id))
        end

208
        expose :issues, if: -> (project, options) { issues_available?(project, options) } do |project|
209 210 211
          expose_url(api_v4_projects_issues_path(id: project.id))
        end

212
        expose :merge_requests, if: -> (project, options) { mrs_available?(project, options) } do |project|
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
          expose_url(api_v4_projects_merge_requests_path(id: project.id))
        end

        expose :repo_branches do |project|
          expose_url(api_v4_projects_repository_branches_path(id: project.id))
        end

        expose :labels do |project|
          expose_url(api_v4_projects_labels_path(id: project.id))
        end

        expose :events do |project|
          expose_url(api_v4_projects_events_path(id: project.id))
        end

        expose :members do |project|
          expose_url(api_v4_projects_members_path(id: project.id))
        end
      end

233
      expose :archived?, as: :archived
234
      expose :visibility
235
      expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
236
      expose :resolve_outdated_diff_discussions
F
Felipe Artur 已提交
237 238 239
      expose :container_registry_enabled

      # Expose old field names with the new permissions methods to keep API compatible
240 241 242
      expose(:issues_enabled) { |project, options| project.feature_available?(:issues, options[:current_user]) }
      expose(:merge_requests_enabled) { |project, options| project.feature_available?(:merge_requests, options[:current_user]) }
      expose(:wiki_enabled) { |project, options| project.feature_available?(:wiki, options[:current_user]) }
243
      expose(:jobs_enabled) { |project, options| project.feature_available?(:builds, options[:current_user]) }
244
      expose(:snippets_enabled) { |project, options| project.feature_available?(:snippets, options[:current_user]) }
F
Felipe Artur 已提交
245

246 247
      expose :shared_runners_enabled
      expose :lfs_enabled?, as: :lfs_enabled
248
      expose :creator_id
249
      expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda { |project, options| project.forked? }
250 251
      expose :import_status
      expose :import_error, if: lambda { |_project, options| options[:user_can_admin_project] }
252

253
      expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:current_user]) }
254
      expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
255
      expose :public_builds, as: :public_jobs
256
      expose :ci_config_path
257
      expose :shared_with_groups do |project, options|
258
        SharedGroup.represent(project.project_group_links, options)
259
      end
J
James Lopez 已提交
260
      expose :only_allow_merge_if_pipeline_succeeds
261
      expose :request_access_enabled
262
      expose :only_allow_merge_if_all_discussions_are_resolved
263
      expose :printing_merge_request_link_enabled
264
      expose :merge_method
M
Markus Koller 已提交
265 266

      expose :statistics, using: 'API::Entities::ProjectStatistics', if: :statistics
267

268
      # rubocop: disable CodeReuse/ActiveRecord
269
      def self.preload_relation(projects_relation, options =  {})
270 271 272 273
        # Preloading tags, should be done with using only `:tags`,
        # as `:tags` are defined as: `has_many :tags, through: :taggings`
        # N+1 is solved then by using `subject.tags.map(&:name)`
        # MR describing the solution: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20555
274 275 276
        super(projects_relation).preload(:group)
                                .preload(project_group_links: :group,
                                         fork_network: :root_project,
277
                                         fork_network_member: :forked_from_project,
278
                                         forked_from_project: [:route, :forks, :tags, namespace: :route])
279
      end
280
      # rubocop: enable CodeReuse/ActiveRecord
281 282

      def self.forks_counting_projects(projects_relation)
283
        projects_relation + projects_relation.map(&:forked_from_project).compact
284
      end
M
Markus Koller 已提交
285 286 287 288 289 290 291
    end

    class ProjectStatistics < Grape::Entity
      expose :commit_count
      expose :storage_size
      expose :repository_size
      expose :lfs_objects_size
292
      expose :build_artifacts_size, as: :job_artifacts_size
N
Nihad Abbasov 已提交
293 294
    end

295 296 297 298
    class Member < Grape::Entity
      expose :user, merge: true, using: UserBasic
      expose :access_level
      expose :expires_at
299 300
    end

301 302 303
    class AccessRequester < Grape::Entity
      expose :user, merge: true, using: UserBasic
      expose :requested_at
M
miks 已提交
304 305
    end

306 307 308 309 310 311 312 313
    class BasicGroupDetails < Grape::Entity
      expose :id
      expose :web_url
      expose :name
    end

    class Group < BasicGroupDetails
      expose :path, :description, :visibility
314
      expose :lfs_enabled?, as: :lfs_enabled
315 316
      expose :avatar_url do |group, options|
        group.avatar_url(only_path: false)
317
      end
318
      expose :request_access_enabled
319
      expose :full_name, :full_path
320 321 322 323

      if ::Group.supports_nested_groups?
        expose :parent_id
      end
M
Markus Koller 已提交
324

325 326
      expose :custom_attributes, using: 'API::Entities::CustomAttribute', if: :with_custom_attributes

M
Markus Koller 已提交
327 328 329 330 331
      expose :statistics, if: :statistics do
        with_options format_with: -> (value) { value.to_i } do
          expose :storage_size
          expose :repository_size
          expose :lfs_objects_size
332
          expose :build_artifacts_size, as: :job_artifacts_size
M
Markus Koller 已提交
333 334
        end
      end
335
    end
A
Andrew8xx8 已提交
336

337
    class GroupDetail < Group
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
      expose :projects, using: Entities::Project do |group, options|
        GroupProjectsFinder.new(
          group: group,
          current_user: options[:current_user],
          options: { only_owned: true }
        ).execute
      end

      expose :shared_projects, using: Entities::Project do |group, options|
        GroupProjectsFinder.new(
          group: group,
          current_user: options[:current_user],
          options: { only_shared: true }
        ).execute
      end
353 354
    end

355 356 357 358
    class DiffRefs < Grape::Entity
      expose :base_sha, :head_sha, :start_sha
    end

359
    class Commit < Grape::Entity
360 361 362 363 364 365 366
      expose :id, :short_id, :title, :created_at
      expose :parent_ids
      expose :safe_message, as: :message
      expose :author_name, :author_email, :authored_date
      expose :committer_name, :committer_email, :committed_date
    end

367
    class CommitStats < Grape::Entity
368 369 370
      expose :additions, :deletions, :total
    end

371 372 373 374
    class CommitWithStats < Commit
      expose :stats, using: Entities::CommitStats
    end

375
    class CommitDetail < Commit
376
      expose :stats, using: Entities::CommitStats, if: :stats
377
      expose :status
378
      expose :last_pipeline, using: 'API::Entities::PipelineBasic'
379
      expose :project_id
380 381
    end

382
    class BasicRef < Grape::Entity
383
      expose :type, :name
384 385
    end

R
Robert Schilling 已提交
386
    class Branch < Grape::Entity
387 388
      expose :name

389
      expose :commit, using: Entities::Commit do |repo_branch, options|
390
        options[:project].repository.commit(repo_branch.dereferenced_target)
391 392
      end

R
Robert Schilling 已提交
393
      expose :merged do |repo_branch, options|
394 395 396 397 398
        if options[:merged_branch_names]
          options[:merged_branch_names].include?(repo_branch.name)
        else
          options[:project].repository.merged_to_root_ref?(repo_branch)
        end
R
Robert Schilling 已提交
399 400
      end

401
      expose :protected do |repo_branch, options|
E
Eric 已提交
402
        ::ProtectedBranch.protected?(options[:project], repo_branch.name)
403 404
      end

405
      expose :developers_can_push do |repo_branch, options|
406
        options[:project].protected_branches.developers_can?(:push, repo_branch.name)
407
      end
408

409
      expose :developers_can_merge do |repo_branch, options|
410
        options[:project].protected_branches.developers_can?(:merge, repo_branch.name)
411 412 413 414
      end

      expose :can_push do |repo_branch, options|
        Gitlab::UserAccess.new(options[:current_user], project: options[:project]).can_push_to_branch?(repo_branch.name)
415
      end
416 417 418 419

      expose :default do |repo_branch, options|
        options[:project].default_branch == repo_branch.name
      end
N
Nihad Abbasov 已提交
420
    end
N
Nihad Abbasov 已提交
421

422
    class TreeObject < Grape::Entity
423
      expose :id, :name, :type, :path
424 425

      expose :mode do |obj, options|
M
mhasbini 已提交
426
        filemode = obj.mode
427 428 429 430 431
        filemode = "0" + filemode if filemode.length < 6
        filemode
      end
    end

J
Jarka Kadlecová 已提交
432
    class Snippet < Grape::Entity
433
      expose :id, :title, :file_name, :description, :visibility
434
      expose :author, using: Entities::UserBasic
R
Robert Speicher 已提交
435
      expose :updated_at, :created_at
J
Jarka Kadlecová 已提交
436 437
      expose :project_id
      expose :web_url do |snippet|
438 439
        Gitlab::UrlBuilder.build(snippet)
      end
N
Nihad Abbasov 已提交
440
    end
N
Nihad Abbasov 已提交
441

J
Jarka Kadlecová 已提交
442 443
    class ProjectSnippet < Snippet
    end
444

J
Jarka Kadlecová 已提交
445
    class PersonalSnippet < Snippet
446 447 448 449 450
      expose :raw_url do |snippet|
        Gitlab::UrlBuilder.build(snippet) + "/raw"
      end
    end

451 452
    class ProjectEntity < Grape::Entity
      expose :id, :iid
F
Felipe Artur 已提交
453
      expose(:project_id) { |entity| entity&.project.try(:id) }
454 455
      expose :title, :description
      expose :state, :created_at, :updated_at
456 457
    end

458
    class Diff < Grape::Entity
M
micael.bergeron 已提交
459
      expose :old_path, :new_path, :a_mode, :b_mode
460 461 462
      expose :new_file?, as: :new_file
      expose :renamed_file?, as: :renamed_file
      expose :deleted_file?, as: :deleted_file
463
      expose :json_safe_diff, as: :diff
464 465
    end

E
Eric 已提交
466 467 468 469 470 471 472 473 474 475 476 477 478
    class ProtectedRefAccess < Grape::Entity
      expose :access_level
      expose :access_level_description do |protected_ref_access|
        protected_ref_access.humanize
      end
    end

    class ProtectedBranch < Grape::Entity
      expose :name
      expose :push_access_levels, using: Entities::ProtectedRefAccess
      expose :merge_access_levels, using: Entities::ProtectedRefAccess
    end

R
Robert Schilling 已提交
479 480 481 482 483
    class ProtectedTag < Grape::Entity
      expose :name
      expose :create_access_levels, using: Entities::ProtectedRefAccess
    end

F
Felipe Artur 已提交
484 485
    class Milestone < Grape::Entity
      expose :id, :iid
F
Felipe Artur 已提交
486 487
      expose :project_id, if: -> (entity, options) { entity&.project_id }
      expose :group_id, if: -> (entity, options) { entity&.group_id }
F
Felipe Artur 已提交
488 489
      expose :title, :description
      expose :state, :created_at, :updated_at
490
      expose :due_date
V
Valery Sizov 已提交
491
      expose :start_date
492 493 494 495

      expose :web_url do |milestone, _options|
        Gitlab::UrlBuilder.build(milestone)
      end
N
Nihad Abbasov 已提交
496 497
    end

498
    class IssueBasic < ProjectEntity
499
      expose :closed_at
H
haseeb 已提交
500
      expose :closed_by, using: Entities::UserBasic
501 502 503 504
      expose :labels do |issue, options|
        # Avoids an N+1 query since labels are preloaded
        issue.labels.map(&:title).sort
      end
505
      expose :milestone, using: Entities::Milestone
506 507 508 509 510
      expose :assignees, :author, using: Entities::UserBasic

      expose :assignee, using: ::API::Entities::UserBasic do |issue, options|
        issue.assignees.first
      end
511

Z
Z.J. van de Weg 已提交
512
      expose :user_notes_count
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
      expose :upvotes do |issue, options|
        if options[:issuable_metadata]
          # Avoids an N+1 query when metadata is included
          options[:issuable_metadata][issue.id].upvotes
        else
          issue.upvotes
        end
      end
      expose :downvotes do |issue, options|
        if options[:issuable_metadata]
          # Avoids an N+1 query when metadata is included
          options[:issuable_metadata][issue.id].downvotes
        else
          issue.downvotes
        end
      end
529
      expose :due_date
530
      expose :confidential
531
      expose :discussion_locked
532 533 534 535

      expose :web_url do |issue, options|
        Gitlab::UrlBuilder.build(issue)
      end
536 537 538 539

      expose :time_stats, using: 'API::Entities::IssuableTimeStats' do |issue|
        issue
      end
N
Nihad Abbasov 已提交
540
    end
A
Alex Denisov 已提交
541

542
    class Issue < IssueBasic
543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
      include ::API::Helpers::RelatedResourcesHelpers

      expose :_links do
        expose :self do |issue|
          expose_url(api_v4_project_issue_path(id: issue.project_id, issue_iid: issue.iid))
        end

        expose :notes do |issue|
          expose_url(api_v4_projects_issues_notes_path(id: issue.project_id, noteable_id: issue.iid))
        end

        expose :award_emoji do |issue|
          expose_url(api_v4_projects_issues_award_emoji_path(id: issue.project_id, issue_iid: issue.iid))
        end

        expose :project do |issue|
          expose_url(api_v4_projects_path(id: issue.project_id))
        end
      end

563 564 565 566 567
      expose :subscribed do |issue, options|
        issue.subscribed?(options[:current_user], options[:project] || issue.project)
      end
    end

568
    class IssuableTimeStats < Grape::Entity
569 570 571 572
      format_with(:time_tracking_formatter) do |time_spent|
        Gitlab::TimeTrackingFormatter.output(time_spent)
      end

573 574 575
      expose :time_estimate
      expose :total_time_spent
      expose :human_time_estimate
576 577 578 579 580

      with_options(format_with: :time_tracking_formatter) do
        expose :total_time_spent, as: :human_total_time_spent
      end

581
      # rubocop: disable CodeReuse/ActiveRecord
582 583 584 585
      def total_time_spent
        # Avoids an N+1 query since timelogs are preloaded
        object.timelogs.map(&:time_spent).sum
      end
586
      # rubocop: enable CodeReuse/ActiveRecord
587 588
    end

589 590 591 592 593
    class ExternalIssue < Grape::Entity
      expose :title
      expose :id
    end

H
haseeb 已提交
594 595
    class PipelineBasic < Grape::Entity
      expose :id, :sha, :ref, :status
596 597 598 599

      expose :web_url do |pipeline, _options|
        Gitlab::Routing.url_helpers.project_pipeline_url(pipeline.project, pipeline)
      end
H
haseeb 已提交
600 601
    end

S
Stan Hu 已提交
602 603 604 605 606 607 608
    class MergeRequestSimple < ProjectEntity
      expose :title
      expose :web_url do |merge_request, options|
        Gitlab::UrlBuilder.build(merge_request)
      end
    end

609
    class MergeRequestBasic < ProjectEntity
610
      expose :title_html, if: -> (_, options) { options[:render_html] } do |entity|
P
Phil Hughes 已提交
611
        MarkupHelper.markdown_field(entity, :title)
612 613
      end
      expose :description_html, if: -> (_, options) { options[:render_html] } do |entity|
P
Phil Hughes 已提交
614
        MarkupHelper.markdown_field(entity, :description)
615
      end
V
Valery Sizov 已提交
616
      expose :target_branch, :source_branch
617 618 619 620 621 622 623 624 625 626 627 628 629 630
      expose :upvotes do |merge_request, options|
        if options[:issuable_metadata]
          options[:issuable_metadata][merge_request.id].upvotes
        else
          merge_request.upvotes
        end
      end
      expose :downvotes do |merge_request, options|
        if options[:issuable_metadata]
          options[:issuable_metadata][merge_request.id].downvotes
        else
          merge_request.downvotes
        end
      end
631 632
      expose :author, :assignee, using: Entities::UserBasic
      expose :source_project_id, :target_project_id
633 634 635 636
      expose :labels do |merge_request, options|
        # Avoids an N+1 query since labels are preloaded
        merge_request.labels.map(&:title).sort
      end
B
Ben Boeckel 已提交
637
      expose :work_in_progress?, as: :work_in_progress
638
      expose :milestone, using: Entities::Milestone
J
James Lopez 已提交
639
      expose :merge_when_pipeline_succeeds
640 641 642 643 644 645

      # Ideally we should deprecate `MergeRequest#merge_status` exposure and
      # use `MergeRequest#mergeable?` instead (boolean).
      # See https://gitlab.com/gitlab-org/gitlab-ce/issues/42344 for more
      # information.
      expose :merge_status do |merge_request|
646 647
        merge_request.check_if_can_be_merged
        merge_request.merge_status
648
      end
649 650
      expose :diff_head_sha, as: :sha
      expose :merge_commit_sha
Z
Z.J. van de Weg 已提交
651
      expose :user_notes_count
652
      expose :discussion_locked
653 654
      expose :should_remove_source_branch?, as: :should_remove_source_branch
      expose :force_remove_source_branch?, as: :force_remove_source_branch
655 656 657
      expose :allow_collaboration, if: -> (merge_request, _) { merge_request.for_fork? }
      # Deprecated
      expose :allow_collaboration, as: :allow_maintainer_to_push, if: -> (merge_request, _) { merge_request.for_fork? }
658 659 660 661

      expose :web_url do |merge_request, options|
        Gitlab::UrlBuilder.build(merge_request)
      end
662 663 664 665

      expose :time_stats, using: 'API::Entities::IssuableTimeStats' do |merge_request|
        merge_request
      end
666 667

      expose :squash
A
Alex Denisov 已提交
668
    end
V
Valeriy Sizov 已提交
669

670 671 672 673
    class MergeRequest < MergeRequestBasic
      expose :subscribed do |merge_request, options|
        merge_request.subscribed?(options[:current_user], options[:project])
      end
674 675 676 677

      expose :changes_count do |merge_request, _options|
        merge_request.merge_request_diff.real_size
      end
H
haseeb 已提交
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710

      expose :merged_by, using: Entities::UserBasic do |merge_request, _options|
        merge_request.metrics&.merged_by
      end

      expose :merged_at do |merge_request, _options|
        merge_request.metrics&.merged_at
      end

      expose :closed_by, using: Entities::UserBasic do |merge_request, _options|
        merge_request.metrics&.latest_closed_by
      end

      expose :closed_at do |merge_request, _options|
        merge_request.metrics&.latest_closed_at
      end

      expose :latest_build_started_at, if: -> (_, options) { build_available?(options) } do |merge_request, _options|
        merge_request.metrics&.latest_build_started_at
      end

      expose :latest_build_finished_at, if: -> (_, options) { build_available?(options) } do |merge_request, _options|
        merge_request.metrics&.latest_build_finished_at
      end

      expose :first_deployed_to_production_at, if: -> (_, options) { build_available?(options) } do |merge_request, _options|
        merge_request.metrics&.first_deployed_to_production_at
      end

      expose :pipeline, using: Entities::PipelineBasic, if: -> (_, options) { build_available?(options) } do |merge_request, _options|
        merge_request.metrics&.pipeline
      end

711 712
      expose :diff_refs, using: Entities::DiffRefs

713 714
      expose :diverged_commits_count, as: :diverged_commits_count, if: -> (_, options) { options[:include_diverged_commits_count] }

H
haseeb 已提交
715 716 717
      def build_available?(options)
        options[:project]&.feature_available?(:builds, options[:current_user])
      end
718 719
    end

720
    class MergeRequestChanges < MergeRequest
721
      expose :diffs, as: :changes, using: Entities::Diff do |compare, _|
D
Douwe Maan 已提交
722
        compare.raw_diffs(limits: false).to_a
723 724 725
      end
    end

726 727 728
    class MergeRequestDiff < Grape::Entity
      expose :id, :head_commit_sha, :base_commit_sha, :start_commit_sha,
        :created_at, :merge_request_id, :state, :real_size
729
    end
730

731
    class MergeRequestDiffFull < MergeRequestDiff
732
      expose :commits, using: Entities::Commit
733

734
      expose :diffs, using: Entities::Diff do |compare, _|
D
Douwe Maan 已提交
735
        compare.raw_diffs(limits: false).to_a
736 737 738
      end
    end

739
    class SSHKey < Grape::Entity
740
      expose :id, :title, :key, :created_at
V
Valeriy Sizov 已提交
741
    end
742

743
    class SSHKeyWithUser < SSHKey
744
      expose :user, using: Entities::UserPublic
745 746
    end

747 748 749 750 751
    class DeployKeysProject < Grape::Entity
      expose :deploy_key, merge: true, using: Entities::SSHKey
      expose :can_push
    end

R
Robert Schilling 已提交
752 753 754 755
    class GPGKey < Grape::Entity
      expose :id, :key, :created_at
    end

756 757 758 759 760
    class DiffPosition < Grape::Entity
      expose :base_sha, :start_sha, :head_sha, :old_path, :new_path,
        :position_type
    end

761
    class Note < Grape::Entity
S
sue445 已提交
762 763 764
      # Only Issue and MergeRequest have iid
      NOTEABLE_TYPES_WITH_IID = %w(Issue MergeRequest).freeze

765
      expose :id
J
Jan Provaznik 已提交
766
      expose :type
767
      expose :note, as: :body
768
      expose :attachment_identifier, as: :attachment
769
      expose :author, using: Entities::UserBasic
770
      expose :created_at, :updated_at
771
      expose :system?, as: :system
D
Dmitriy Zaporozhets 已提交
772
      expose :noteable_id, :noteable_type
S
sue445 已提交
773

774
      expose :position, if: ->(note, options) { note.is_a?(DiffNote) } do |note|
775 776 777 778 779 780 781
        note.position.to_h
      end

      expose :resolvable?, as: :resolvable
      expose :resolved?, as: :resolved, if: ->(note, options) { note.resolvable? }
      expose :resolved_by, using: Entities::UserBasic, if: ->(note, options) { note.resolvable? }

S
sue445 已提交
782 783
      # Avoid N+1 queries as much as possible
      expose(:noteable_iid) { |note| note.noteable.iid if NOTEABLE_TYPES_WITH_IID.include?(note.noteable_type) }
784
    end
785

J
Jan Provaznik 已提交
786 787 788 789 790 791
    class Discussion < Grape::Entity
      expose :id
      expose :individual_note?, as: :individual_note
      expose :notes, using: Entities::Note
    end

I
Imre 已提交
792 793 794 795 796 797
    class Avatar < Grape::Entity
      expose :avatar_url do |avatarable, options|
        avatarable.avatar_url(only_path: false, size: options[:size])
      end
    end

Z
Z.J. van de Weg 已提交
798 799 800 801 802 803 804 805
    class AwardEmoji < Grape::Entity
      expose :id
      expose :name
      expose :user, using: Entities::UserBasic
      expose :created_at, :updated_at
      expose :awardable_id, :awardable_type
    end

806 807 808 809
    class MRNote < Grape::Entity
      expose :note
      expose :author, using: Entities::UserBasic
    end
D
Dmitriy Zaporozhets 已提交
810

811 812
    class CommitNote < Grape::Entity
      expose :note
813 814 815
      expose(:path) { |note| note.diff_file.try(:file_path) if note.diff_note? }
      expose(:line) { |note| note.diff_line.try(:new_line) if note.diff_note? }
      expose(:line_type) { |note| note.diff_line.try(:type) if note.diff_note? }
816
      expose :author, using: Entities::UserBasic
817
      expose :created_at
818 819
    end

K
Kamil Trzcinski 已提交
820 821
    class CommitStatus < Grape::Entity
      expose :id, :sha, :ref, :status, :name, :target_url, :description,
822
             :created_at, :started_at, :finished_at, :allow_failure, :coverage
K
Kamil Trzcinski 已提交
823
      expose :author, using: Entities::UserBasic
K
Kamil Trzcinski 已提交
824 825
    end

826 827 828 829 830
    class PushEventPayload < Grape::Entity
      expose :commit_count, :action, :ref_type, :commit_from, :commit_to
      expose :ref, :commit_title
    end

D
Dmitriy Zaporozhets 已提交
831
    class Event < Grape::Entity
832
      expose :project_id, :action_name
S
sue445 已提交
833
      expose :target_id, :target_iid, :target_type, :author_id
834
      expose :target_title
835
      expose :created_at
D
Dmitriy Zaporozhets 已提交
836 837
      expose :note, using: Entities::Note, if: ->(event, options) { event.note? }
      expose :author, using: Entities::UserBasic, if: ->(event, options) { event.author }
838

839 840 841 842 843
      expose :push_event_payload,
        as: :push_data,
        using: PushEventPayload,
        if: -> (event, _) { event.push? }

844
      expose :author_username do |event, options|
Z
Z.J. van de Weg 已提交
845
        event.author&.username
846
      end
D
Dmitriy Zaporozhets 已提交
847
    end
848

849
    class ProjectGroupLink < Grape::Entity
850
      expose :id, :project_id, :group_id, :group_access, :expires_at
851 852
    end

D
Douglas Barbosa Alexandre 已提交
853 854
    class Todo < Grape::Entity
      expose :id
855 856
      expose :project, using: Entities::ProjectIdentity, if: -> (todo, _) { todo.project_id }
      expose :group, using: 'API::Entities::NamespaceBasic', if: -> (todo, _) { todo.group_id }
D
Douglas Barbosa Alexandre 已提交
857
      expose :author, using: Entities::UserBasic
R
Robert Schilling 已提交
858
      expose :action_name
D
Douglas Barbosa Alexandre 已提交
859
      expose :target_type
860 861

      expose :target do |todo, options|
862
        todo_target_class(todo.target_type).represent(todo.target, options)
D
Douglas Barbosa Alexandre 已提交
863 864 865 866
      end

      expose :target_url do |todo, options|
        target_type   = todo.target_type.underscore
867
        target_url    = "#{todo.parent.class.to_s.underscore}_#{target_type}_url"
868
        target_anchor = "note_#{todo.note_id}" if todo.note_id?
D
Douglas Barbosa Alexandre 已提交
869

870 871
        Gitlab::Routing
          .url_helpers
872
          .public_send(target_url, todo.parent, todo.target, anchor: target_anchor) # rubocop:disable GitlabSecurity/PublicSend
D
Douglas Barbosa Alexandre 已提交
873 874 875 876 877
      end

      expose :body
      expose :state
      expose :created_at
878 879 880 881

      def todo_target_class(target_type)
        ::API::Entities.const_get(target_type)
      end
D
Douglas Barbosa Alexandre 已提交
882 883
    end

884
    class NamespaceBasic < Grape::Entity
885
      expose :id, :name, :path, :kind, :full_path, :parent_id
886
    end
887

888
    class Namespace < NamespaceBasic
889 890 891 892 893 894
      expose :members_count_with_descendants, if: -> (namespace, opts) { expose_members_count_with_descendants?(namespace, opts) } do |namespace, _|
        namespace.users_with_descendants.count
      end

      def expose_members_count_with_descendants?(namespace, opts)
        namespace.kind == 'group' && Ability.allowed?(opts[:current_user], :admin_group, namespace)
895
      end
896
    end
897

898
    class MemberAccess < Grape::Entity
D
Dmitriy Zaporozhets 已提交
899
      expose :access_level
900
      expose :notification_level do |member, options|
901 902 903
        if member.notification_setting
          ::NotificationSetting.levels[member.notification_setting.level]
        end
904
      end
905 906
    end

907
    class ProjectAccess < MemberAccess
908 909
    end

910
    class GroupAccess < MemberAccess
911 912
    end

913 914 915
    class NotificationSetting < Grape::Entity
      expose :level
      expose :events, if: ->(notification_setting, _) { notification_setting.custom? } do
916
        ::NotificationSetting.email_events.each do |event|
917 918 919 920 921 922 923 924 925 926 927
          expose event
        end
      end
    end

    class GlobalNotificationSetting < NotificationSetting
      expose :notification_email do |notification_setting, options|
        notification_setting.user.notification_email
      end
    end

928 929
    class ProjectService < Grape::Entity
      expose :id, :title, :created_at, :updated_at, :active
930 931
      expose :push_events, :issues_events, :confidential_issues_events
      expose :merge_requests_events, :tag_push_events, :note_events
932
      expose :confidential_note_events, :pipeline_events, :wiki_page_events
933
      expose :job_events
934 935
      # Expose serialized properties
      expose :properties do |service, options|
S
Stan Hu 已提交
936
        service.properties.slice(*service.api_field_names)
937 938 939
      end
    end

940 941 942
    class ProjectWithAccess < Project
      expose :permissions do
        expose :project_access, using: Entities::ProjectAccess do |project, options|
943 944
          if options[:project_members]
            options[:project_members].find { |member| member.source_id == project.id }
945 946
          else
            project.project_member(options[:current_user])
947
          end
948 949 950
        end

        expose :group_access, using: Entities::GroupAccess do |project, options|
951
          if project.group
952 953
            if options[:group_members]
              options[:group_members].find { |member| member.source_id == project.namespace_id }
954 955
            else
              project.group.group_member(options[:current_user])
956
            end
957
          end
958 959
        end
      end
960

961
      # rubocop: disable CodeReuse/ActiveRecord
962 963 964
      def self.preload_relation(projects_relation, options = {})
        relation = super(projects_relation, options)

965 966 967 968 969 970 971
        # MySQL doesn't support LIMIT inside an IN subquery
        if Gitlab::Database.mysql?
          project_ids = relation.pluck('projects.id')
          namespace_ids = relation.pluck(:namespace_id)
        else
          project_ids = relation.select('projects.id')
          namespace_ids = relation.select(:namespace_id)
972 973
        end

974 975 976 977 978 979 980 981 982
        options[:project_members] = options[:current_user]
          .project_members
          .where(source_id: project_ids)
          .preload(:source, user: [notification_settings: :source])

        options[:group_members] = options[:current_user]
          .group_members
          .where(source_id: namespace_ids)
          .preload(:source, user: [notification_settings: :source])
983 984 985

        relation
      end
986
      # rubocop: enable CodeReuse/ActiveRecord
987
    end
988

A
Andre Guedes 已提交
989
    class LabelBasic < Grape::Entity
R
Rares Sfirlogea 已提交
990
      expose :id, :name, :color, :description
A
Andre Guedes 已提交
991 992 993
    end

    class Label < LabelBasic
994
      expose :open_issues_count do |label, options|
F
Francesco Coda Zabetta 已提交
995 996
        label.open_issues_count(options[:current_user])
      end
997

F
Francesco Coda Zabetta 已提交
998 999 1000
      expose :closed_issues_count do |label, options|
        label.closed_issues_count(options[:current_user])
      end
1001

F
Francesco Coda Zabetta 已提交
1002 1003
      expose :open_merge_requests_count do |label, options|
        label.open_merge_requests_count(options[:current_user])
1004 1005
      end

1006 1007 1008
      expose :priority do |label, options|
        label.priority(options[:project])
      end
1009 1010

      expose :subscribed do |label, options|
1011
        label.subscribed?(options[:current_user], options[:project])
1012
      end
1013
    end
1014

A
Andre Guedes 已提交
1015 1016 1017 1018 1019 1020 1021 1022
    class List < Grape::Entity
      expose :id
      expose :label, using: Entities::LabelBasic
      expose :position
    end

    class Board < Grape::Entity
      expose :id
F
Felipe Artur 已提交
1023 1024
      expose :project, using: Entities::BasicProjectDetails

A
Andre Guedes 已提交
1025 1026 1027 1028 1029
      expose :lists, using: Entities::List do |board|
        board.lists.destroyable
      end
    end

1030
    class Compare < Grape::Entity
1031 1032
      expose :commit, using: Entities::Commit do |compare, options|
        ::Commit.decorate(compare.commits, nil).last
1033
      end
1034

1035 1036
      expose :commits, using: Entities::Commit do |compare, options|
        ::Commit.decorate(compare.commits, nil)
1037
      end
1038

1039
      expose :diffs, using: Entities::Diff do |compare, options|
D
Douwe Maan 已提交
1040
        compare.diffs(limits: false).to_a
1041
      end
1042 1043

      expose :compare_timeout do |compare, options|
J
Jacob Vosmaer 已提交
1044
        compare.diffs.overflow?
1045 1046 1047
      end

      expose :same, as: :compare_same_ref
1048
    end
1049 1050 1051 1052

    class Contributor < Grape::Entity
      expose :name, :email, :commits, :additions, :deletions
    end
D
Douwe Maan 已提交
1053 1054 1055 1056

    class BroadcastMessage < Grape::Entity
      expose :message, :starts_at, :ends_at, :color, :font
    end
1057 1058

    class ApplicationSetting < Grape::Entity
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
      def self.exposed_attributes
        attributes = ::ApplicationSettingsHelper.visible_attributes
        attributes.delete(:performance_bar_allowed_group_path)
        attributes.delete(:performance_bar_enabled)

        attributes
      end

      expose :id, :performance_bar_allowed_group_id
      expose(*exposed_attributes)
1069 1070 1071 1072 1073 1074
      expose(:restricted_visibility_levels) do |setting, _options|
        setting.restricted_visibility_levels.map { |level| Gitlab::VisibilityLevel.string_level(level) }
      end
      expose(:default_project_visibility) { |setting, _options| Gitlab::VisibilityLevel.string_level(setting.default_project_visibility) }
      expose(:default_snippet_visibility) { |setting, _options| Gitlab::VisibilityLevel.string_level(setting.default_snippet_visibility) }
      expose(:default_group_visibility) { |setting, _options| Gitlab::VisibilityLevel.string_level(setting.default_group_visibility) }
1075 1076 1077 1078

      # support legacy names, can be removed in v5
      expose :password_authentication_enabled_for_web, as: :password_authentication_enabled
      expose :password_authentication_enabled_for_web, as: :signin_enabled
1079
    end
D
Dmitriy Zaporozhets 已提交
1080 1081

    class Release < Grape::Entity
1082 1083
      expose :tag, as: :tag_name
      expose :description
D
Dmitriy Zaporozhets 已提交
1084
    end
1085

R
Robert Schilling 已提交
1086
    class Tag < Grape::Entity
1087
      expose :name, :message, :target
1088

1089
      expose :commit, using: Entities::Commit do |repo_tag, options|
1090
        options[:project].repository.commit(repo_tag.dereferenced_target)
1091 1092
      end

1093
      # rubocop: disable CodeReuse/ActiveRecord
1094 1095
      expose :release, using: Entities::Release do |repo_tag, options|
        options[:project].releases.find_by(tag: repo_tag.name)
1096
      end
1097
      # rubocop: enable CodeReuse/ActiveRecord
1098
    end
K
Kamil Trzcinski 已提交
1099

T
Tomasz Maczukin 已提交
1100
    class Runner < Grape::Entity
T
Tomasz Maczukin 已提交
1101 1102
      expose :id
      expose :description
1103
      expose :ip_address
T
Tomasz Maczukin 已提交
1104
      expose :active
1105
      expose :instance_type?, as: :is_shared
T
Tomasz Maczukin 已提交
1106
      expose :name
1107
      expose :online?, as: :online
1108
      expose :status
T
Tomasz Maczukin 已提交
1109 1110
    end

1111 1112
    class RunnerDetails < Runner
      expose :tag_list
1113
      expose :run_untagged
1114
      expose :locked
1115
      expose :maximum_timeout
S
Shinya Maeda 已提交
1116
      expose :access_level
1117
      expose :version, :revision, :platform, :architecture
1118
      expose :contacted_at
1119
      expose :token, if: lambda { |runner, options| options[:current_user].admin? || !runner.instance_type? }
1120
      # rubocop: disable CodeReuse/ActiveRecord
1121
      expose :projects, with: Entities::BasicProjectDetails do |runner, options|
B
blackst0ne 已提交
1122
        if options[:current_user].admin?
1123 1124
          runner.projects
        else
1125
          options[:current_user].authorized_projects.where(id: runner.projects)
1126 1127
        end
      end
1128 1129
      # rubocop: enable CodeReuse/ActiveRecord
      # rubocop: disable CodeReuse/ActiveRecord
1130 1131 1132 1133 1134 1135 1136
      expose :groups, with: Entities::BasicGroupDetails do |runner, options|
        if options[:current_user].admin?
          runner.groups
        else
          options[:current_user].authorized_groups.where(id: runner.groups)
        end
      end
1137
      # rubocop: enable CodeReuse/ActiveRecord
1138 1139
    end

1140 1141 1142 1143
    class RunnerRegistrationDetails < Grape::Entity
      expose :id, :token
    end

1144
    class JobArtifactFile < Grape::Entity
1145 1146 1147
      expose :filename, :size
    end

1148 1149 1150 1151
    class JobArtifact < Grape::Entity
      expose :file_type, :size, :filename, :file_format
    end

T
Tomasz Maczukin 已提交
1152
    class JobBasic < Grape::Entity
T
Tomasz Maczukin 已提交
1153
      expose :id, :status, :stage, :name, :ref, :tag, :coverage
T
Tomasz Maczukin 已提交
1154
      expose :created_at, :started_at, :finished_at
M
Mehdi Lahmam 已提交
1155
      expose :duration
T
Tomasz Maczukin 已提交
1156
      expose :user, with: User
1157
      expose :commit, with: Commit
1158
      expose :pipeline, with: PipelineBasic
1159 1160 1161 1162

      expose :web_url do |job, _options|
        Gitlab::Routing.url_helpers.project_job_url(job.project, job)
      end
1163
    end
1164

T
Tomasz Maczukin 已提交
1165
    class Job < JobBasic
1166
      # artifacts_file is included in job_artifacts, but kept for backward compatibility (remove in api/v5)
T
Tomasz Maczukin 已提交
1167
      expose :artifacts_file, using: JobArtifactFile, if: -> (job, opts) { job.artifacts? }
1168
      expose :job_artifacts, as: :artifacts, using: JobArtifact
T
Tomasz Maczukin 已提交
1169
      expose :runner, with: Runner
1170
      expose :artifacts_expire_at
T
Tomasz Maczukin 已提交
1171 1172 1173
    end

    class JobBasicWithProject < JobBasic
T
Tomasz Maczukin 已提交
1174 1175 1176
      expose :project, with: ProjectIdentity
    end

T
Tomasz Maczukin 已提交
1177
    class Trigger < Grape::Entity
1178
      expose :id
1179
      expose :token, :description
1180
      expose :created_at, :updated_at, :last_used
1181
      expose :owner, using: Entities::UserBasic
T
Tomasz Maczukin 已提交
1182
    end
1183

1184
    class Variable < Grape::Entity
T
Tomasz Maczukin 已提交
1185
      expose :key, :value
S
Shinya Maeda 已提交
1186
      expose :protected?, as: :protected, if: -> (entity, _) { entity.respond_to?(:protected?) }
1187
    end
1188

1189 1190
    class Pipeline < PipelineBasic
      expose :before_sha, :tag, :yaml_errors
Z
Z.J. van de Weg 已提交
1191 1192 1193 1194

      expose :user, with: Entities::UserBasic
      expose :created_at, :updated_at, :started_at, :finished_at, :committed_at
      expose :duration
1195
      expose :coverage
Z
Z.J. van de Weg 已提交
1196 1197
    end

1198 1199 1200
    class PipelineSchedule < Grape::Entity
      expose :id
      expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active
1201
      expose :created_at, :updated_at
1202 1203 1204
      expose :owner, using: Entities::UserBasic
    end

S
Shinya Maeda 已提交
1205 1206
    class PipelineScheduleDetails < PipelineSchedule
      expose :last_pipeline, using: Entities::PipelineBasic
1207
      expose :variables, using: Entities::Variable
S
Shinya Maeda 已提交
1208 1209
    end

1210
    class EnvironmentBasic < Grape::Entity
N
Nick Thomas 已提交
1211
      expose :id, :name, :slug, :external_url
1212 1213
    end

1214
    class Environment < EnvironmentBasic
1215
      expose :project, using: Entities::BasicProjectDetails
Z
Z.J. van de Weg 已提交
1216 1217 1218 1219
    end

    class Deployment < Grape::Entity
      expose :id, :iid, :ref, :sha, :created_at
1220 1221
      expose :user,        using: Entities::UserBasic
      expose :environment, using: Entities::EnvironmentBasic
1222
      expose :deployable,  using: Entities::Job
1223 1224
    end

J
J.D. Bean 已提交
1225
    class LicenseBasic < Grape::Entity
1226
      expose :key, :name, :nickname
1227 1228
      expose :url, as: :html_url
      expose(:source_url) { |license| license.meta['source'] }
J
J.D. Bean 已提交
1229 1230 1231 1232
    end

    class License < LicenseBasic
      expose :popular?, as: :popular
1233
      expose(:description) { |license| license.meta['description'] }
1234 1235 1236
      expose(:conditions) { |license| license.meta['conditions'] }
      expose(:permissions) { |license| license.meta['permissions'] }
      expose(:limitations) { |license| license.meta['limitations'] }
1237 1238
      expose :content
    end
1239

Z
ZJ van de Weg 已提交
1240
    class TemplatesList < Grape::Entity
N
Nick Thomas 已提交
1241
      expose :key
1242 1243 1244
      expose :name
    end

Z
ZJ van de Weg 已提交
1245
    class Template < Grape::Entity
1246 1247
      expose :name, :content
    end
1248 1249 1250 1251 1252

    class BroadcastMessage < Grape::Entity
      expose :id, :message, :starts_at, :ends_at, :color, :font
      expose :active?, as: :active
    end
T
Tomasz Maczukin 已提交
1253

1254
    class PersonalAccessToken < Grape::Entity
1255 1256 1257 1258 1259 1260 1261
      expose :id, :name, :revoked, :created_at, :scopes
      expose :active?, as: :active
      expose :expires_at do |personal_access_token|
        personal_access_token.expires_at ? personal_access_token.expires_at.strftime("%Y-%m-%d") : nil
      end
    end

1262
    class PersonalAccessTokenWithToken < PersonalAccessToken
1263 1264
      expose :token
    end
1265 1266 1267 1268

    class ImpersonationToken < PersonalAccessTokenWithToken
      expose :impersonation
    end
1269

1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
    class FeatureGate < Grape::Entity
      expose :key
      expose :value
    end

    class Feature < Grape::Entity
      expose :name
      expose :state
      expose :gates, using: FeatureGate do |model|
        model.gates.map do |gate|
          value = model.gate_values[gate.key]

          # By default all gate values are populated. Only show relevant ones.
          if (value.is_a?(Integer) && value.zero?) || (value.is_a?(Set) && value.empty?)
            next
          end

          { key: gate.key, value: value }
        end.compact
      end
    end

1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307
    module JobRequest
      class JobInfo < Grape::Entity
        expose :name, :stage
        expose :project_id, :project_name
      end

      class GitInfo < Grape::Entity
        expose :repo_url, :ref, :sha, :before_sha
        expose :ref_type do |model|
          if model.tag
            'tag'
          else
            'branch'
          end
        end
      end
T
Tomasz Maczukin 已提交
1308

1309
      class RunnerInfo < Grape::Entity
T
Tomasz Maczukin 已提交
1310
        expose :metadata_timeout, as: :timeout
F
Francisco Javier López 已提交
1311
        expose :runner_session_url
1312
      end
T
Tomasz Maczukin 已提交
1313

1314
      class Step < Grape::Entity
T
Tomasz Maczukin 已提交
1315
        expose :name, :script, :timeout, :when, :allow_failure
1316
      end
T
Tomasz Maczukin 已提交
1317

1318
      class Image < Grape::Entity
1319 1320 1321
        expose :name, :entrypoint
      end

1322
      class Service < Image
1323
        expose :alias, :command
1324
      end
T
Tomasz Maczukin 已提交
1325

1326
      class Artifacts < Grape::Entity
S
Shinya Maeda 已提交
1327 1328 1329 1330 1331 1332 1333
        expose :name
        expose :untracked
        expose :paths
        expose :when
        expose :expire_in
        expose :artifact_type
        expose :artifact_format
T
Tomasz Maczukin 已提交
1334 1335
      end

1336
      class Cache < Grape::Entity
1337
        expose :key, :untracked, :paths, :policy
T
Tomasz Maczukin 已提交
1338 1339
      end

1340 1341 1342
      class Credentials < Grape::Entity
        expose :type, :url, :username, :password
      end
T
Tomasz Maczukin 已提交
1343

1344
      class Dependency < Grape::Entity
T
Tomasz Maczukin 已提交
1345
        expose :id, :name, :token
1346
        expose :artifacts_file, using: JobArtifactFile, if: ->(job, _) { job.artifacts? }
1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368
      end

      class Response < Grape::Entity
        expose :id
        expose :token
        expose :allow_git_fetch

        expose :job_info, using: JobInfo do |model|
          model
        end

        expose :git_info, using: GitInfo do |model|
          model
        end

        expose :runner_info, using: RunnerInfo do |model|
          model
        end

        expose :variables
        expose :steps, using: Step
        expose :image, using: Image
1369
        expose :services, using: Service
1370 1371 1372
        expose :artifacts, using: Artifacts
        expose :cache, using: Cache
        expose :credentials, using: Credentials
T
Tomasz Maczukin 已提交
1373
        expose :dependencies, using: Dependency
1374
        expose :features
1375
      end
T
Tomasz Maczukin 已提交
1376
    end
1377 1378 1379 1380

    class UserAgentDetail < Grape::Entity
      expose :user_agent
      expose :ip_address
J
James Lopez 已提交
1381
      expose :submitted, as: :akismet_submitted
1382
    end
1383

1384 1385 1386 1387
    class CustomAttribute < Grape::Entity
      expose :key
      expose :value
    end
T
Travis Miller 已提交
1388

1389 1390 1391 1392 1393
    class PagesDomainCertificateExpiration < Grape::Entity
      expose :expired?, as: :expired
      expose :expiration
    end

T
Travis Miller 已提交
1394 1395 1396 1397 1398 1399 1400
    class PagesDomainCertificate < Grape::Entity
      expose :subject
      expose :expired?, as: :expired
      expose :certificate
      expose :certificate_text
    end

1401 1402 1403
    class PagesDomainBasic < Grape::Entity
      expose :domain
      expose :url
1404
      expose :project_id
1405 1406 1407 1408
      expose :verified?, as: :verified
      expose :verification_code, as: :verification_code
      expose :enabled_until

1409 1410 1411 1412 1413 1414 1415 1416
      expose :certificate,
        as: :certificate_expiration,
        if: ->(pages_domain, _) { pages_domain.certificate? },
        using: PagesDomainCertificateExpiration do |pages_domain|
        pages_domain
      end
    end

T
Travis Miller 已提交
1417 1418 1419
    class PagesDomain < Grape::Entity
      expose :domain
      expose :url
1420 1421 1422 1423
      expose :verified?, as: :verified
      expose :verification_code, as: :verification_code
      expose :enabled_until

T
Travis Miller 已提交
1424
      expose :certificate,
1425 1426
        if: ->(pages_domain, _) { pages_domain.certificate? },
        using: PagesDomainCertificate do |pages_domain|
T
Travis Miller 已提交
1427 1428 1429
        pages_domain
      end
    end
N
Nicolas MERELLI 已提交
1430 1431

    class Application < Grape::Entity
1432
      expose :id
N
Nicolas MERELLI 已提交
1433
      expose :uid, as: :application_id
1434
      expose :name, as: :application_name
N
Nicolas MERELLI 已提交
1435 1436
      expose :redirect_uri, as: :callback_url
    end
1437 1438 1439 1440 1441

    # Use with care, this exposes the secret
    class ApplicationWithSecret < Application
      expose :secret
    end
J
Jarka Kadlecová 已提交
1442 1443 1444 1445 1446 1447 1448 1449

    class Blob < Grape::Entity
      expose :basename
      expose :data
      expose :filename
      expose :id
      expose :ref
      expose :startline
1450
      expose :project_id
J
Jarka Kadlecová 已提交
1451
    end
1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469

    class BasicBadgeDetails < Grape::Entity
      expose :link_url
      expose :image_url
      expose :rendered_link_url do |badge, options|
        badge.rendered_link_url(options.fetch(:project, nil))
      end
      expose :rendered_image_url do |badge, options|
        badge.rendered_image_url(options.fetch(:project, nil))
      end
    end

    class Badge < BasicBadgeDetails
      expose :id
      expose :kind do |badge|
        badge.type == 'ProjectBadge' ? 'project' : 'group'
      end
    end
1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483

    class ResourceLabelEvent < Grape::Entity
      expose :id
      expose :user, using: Entities::UserBasic
      expose :created_at
      expose :resource_type do |event, options|
        event.issuable.class.name
      end
      expose :resource_id do |event, options|
        event.issuable.id
      end
      expose :label, using: Entities::LabelBasic
      expose :action
    end
N
Nihad Abbasov 已提交
1484 1485
  end
end