entities.rb 45.8 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
I
Imre Farkas 已提交
163
      expose :ssh_url_to_repo, :http_url_to_repo, :web_url, :readme_url
164 165 166
      expose :avatar_url do |project, options|
        project.avatar_url(only_path: false)
      end
167
      expose :star_count, :forks_count
F
Francisco Lopez 已提交
168
      expose :last_activity_at
169

170
      expose :namespace, using: 'API::Entities::NamespaceBasic'
171 172
      expose :custom_attributes, using: 'API::Entities::CustomAttribute', if: :with_custom_attributes

173
      # rubocop: disable CodeReuse/ActiveRecord
174
      def self.preload_relation(projects_relation, options =  {})
175 176 177 178
        # 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
179
        projects_relation.preload(:project_feature, :route)
180 181
                         .preload(:import_state, :tags)
                         .preload(namespace: [:route, :owner])
182
      end
183
      # rubocop: enable CodeReuse/ActiveRecord
184 185
    end

186
    class Project < BasicProjectDetails
187 188 189 190 191 192 193
      include ::API::Helpers::RelatedResourcesHelpers

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

194
        expose :issues, if: -> (project, options) { issues_available?(project, options) } do |project|
195 196 197
          expose_url(api_v4_projects_issues_path(id: project.id))
        end

198
        expose :merge_requests, if: -> (project, options) { mrs_available?(project, options) } do |project|
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
          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

219
      expose :archived?, as: :archived
220
      expose :visibility
221
      expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
222
      expose :resolve_outdated_diff_discussions
F
Felipe Artur 已提交
223 224 225
      expose :container_registry_enabled

      # Expose old field names with the new permissions methods to keep API compatible
226 227 228
      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]) }
229
      expose(:jobs_enabled) { |project, options| project.feature_available?(:builds, options[:current_user]) }
230
      expose(:snippets_enabled) { |project, options| project.feature_available?(:snippets, options[:current_user]) }
F
Felipe Artur 已提交
231

232 233
      expose :shared_runners_enabled
      expose :lfs_enabled?, as: :lfs_enabled
234
      expose :creator_id
235
      expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda { |project, options| project.forked? }
236 237
      expose :import_status
      expose :import_error, if: lambda { |_project, options| options[:user_can_admin_project] }
238

239
      expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:current_user]) }
240
      expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
241
      expose :public_builds, as: :public_jobs
242
      expose :ci_config_path
243
      expose :shared_with_groups do |project, options|
244
        SharedGroup.represent(project.project_group_links, options)
245
      end
J
James Lopez 已提交
246
      expose :only_allow_merge_if_pipeline_succeeds
247
      expose :request_access_enabled
248
      expose :only_allow_merge_if_all_discussions_are_resolved
249
      expose :printing_merge_request_link_enabled
250
      expose :merge_method
M
Markus Koller 已提交
251 252

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

254
      # rubocop: disable CodeReuse/ActiveRecord
255
      def self.preload_relation(projects_relation, options =  {})
256 257 258 259
        # 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
260 261 262 263
        super(projects_relation).preload(:group)
                                .preload(project_group_links: :group,
                                         fork_network: :root_project,
                                         forked_project_link: :forked_from_project,
264
                                         forked_from_project: [:route, :forks, :tags, namespace: :route])
265
      end
266
      # rubocop: enable CodeReuse/ActiveRecord
267 268

      def self.forks_counting_projects(projects_relation)
269
        projects_relation + projects_relation.map(&:forked_from_project).compact
270
      end
M
Markus Koller 已提交
271 272 273 274 275 276 277
    end

    class ProjectStatistics < Grape::Entity
      expose :commit_count
      expose :storage_size
      expose :repository_size
      expose :lfs_objects_size
278
      expose :build_artifacts_size, as: :job_artifacts_size
N
Nihad Abbasov 已提交
279 280
    end

281 282 283 284
    class Member < Grape::Entity
      expose :user, merge: true, using: UserBasic
      expose :access_level
      expose :expires_at
285 286
    end

287 288 289
    class AccessRequester < Grape::Entity
      expose :user, merge: true, using: UserBasic
      expose :requested_at
M
miks 已提交
290 291
    end

292 293 294 295 296 297 298 299
    class BasicGroupDetails < Grape::Entity
      expose :id
      expose :web_url
      expose :name
    end

    class Group < BasicGroupDetails
      expose :path, :description, :visibility
300
      expose :lfs_enabled?, as: :lfs_enabled
301 302
      expose :avatar_url do |group, options|
        group.avatar_url(only_path: false)
303
      end
304
      expose :request_access_enabled
305
      expose :full_name, :full_path
306 307 308 309

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

311 312
      expose :custom_attributes, using: 'API::Entities::CustomAttribute', if: :with_custom_attributes

M
Markus Koller 已提交
313 314 315 316 317
      expose :statistics, if: :statistics do
        with_options format_with: -> (value) { value.to_i } do
          expose :storage_size
          expose :repository_size
          expose :lfs_objects_size
318
          expose :build_artifacts_size, as: :job_artifacts_size
M
Markus Koller 已提交
319 320
        end
      end
321
    end
A
Andrew8xx8 已提交
322

323
    class GroupDetail < Group
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
      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
339 340
    end

341 342 343 344
    class DiffRefs < Grape::Entity
      expose :base_sha, :head_sha, :start_sha
    end

345
    class Commit < Grape::Entity
346 347 348 349 350 351 352
      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

353
    class CommitStats < Grape::Entity
354 355 356
      expose :additions, :deletions, :total
    end

357 358 359 360
    class CommitWithStats < Commit
      expose :stats, using: Entities::CommitStats
    end

361
    class CommitDetail < Commit
362
      expose :stats, using: Entities::CommitStats, if: :stats
363
      expose :status
364
      expose :last_pipeline, using: 'API::Entities::PipelineBasic'
365
      expose :project_id
366 367
    end

368
    class BasicRef < Grape::Entity
369
      expose :type, :name
370 371
    end

R
Robert Schilling 已提交
372
    class Branch < Grape::Entity
373 374
      expose :name

375
      expose :commit, using: Entities::Commit do |repo_branch, options|
376
        options[:project].repository.commit(repo_branch.dereferenced_target)
377 378
      end

R
Robert Schilling 已提交
379
      expose :merged do |repo_branch, options|
380 381 382 383 384
        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 已提交
385 386
      end

387
      expose :protected do |repo_branch, options|
E
Eric 已提交
388
        ::ProtectedBranch.protected?(options[:project], repo_branch.name)
389 390
      end

391
      expose :developers_can_push do |repo_branch, options|
392
        options[:project].protected_branches.developers_can?(:push, repo_branch.name)
393
      end
394

395
      expose :developers_can_merge do |repo_branch, options|
396
        options[:project].protected_branches.developers_can?(:merge, repo_branch.name)
397 398 399 400
      end

      expose :can_push do |repo_branch, options|
        Gitlab::UserAccess.new(options[:current_user], project: options[:project]).can_push_to_branch?(repo_branch.name)
401
      end
402 403 404 405

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

408
    class TreeObject < Grape::Entity
409
      expose :id, :name, :type, :path
410 411

      expose :mode do |obj, options|
M
mhasbini 已提交
412
        filemode = obj.mode
413 414 415 416 417
        filemode = "0" + filemode if filemode.length < 6
        filemode
      end
    end

J
Jarka Kadlecová 已提交
418
    class Snippet < Grape::Entity
419
      expose :id, :title, :file_name, :description, :visibility
420
      expose :author, using: Entities::UserBasic
R
Robert Speicher 已提交
421
      expose :updated_at, :created_at
J
Jarka Kadlecová 已提交
422 423
      expose :project_id
      expose :web_url do |snippet|
424 425
        Gitlab::UrlBuilder.build(snippet)
      end
N
Nihad Abbasov 已提交
426
    end
N
Nihad Abbasov 已提交
427

J
Jarka Kadlecová 已提交
428 429
    class ProjectSnippet < Snippet
    end
430

J
Jarka Kadlecová 已提交
431
    class PersonalSnippet < Snippet
432 433 434 435 436
      expose :raw_url do |snippet|
        Gitlab::UrlBuilder.build(snippet) + "/raw"
      end
    end

437 438
    class ProjectEntity < Grape::Entity
      expose :id, :iid
F
Felipe Artur 已提交
439
      expose(:project_id) { |entity| entity&.project.try(:id) }
440 441
      expose :title, :description
      expose :state, :created_at, :updated_at
442 443
    end

444
    class Diff < Grape::Entity
M
micael.bergeron 已提交
445
      expose :old_path, :new_path, :a_mode, :b_mode
446 447 448
      expose :new_file?, as: :new_file
      expose :renamed_file?, as: :renamed_file
      expose :deleted_file?, as: :deleted_file
449
      expose :json_safe_diff, as: :diff
450 451
    end

E
Eric 已提交
452 453 454 455 456 457 458 459 460 461 462 463 464
    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 已提交
465 466 467 468 469
    class ProtectedTag < Grape::Entity
      expose :name
      expose :create_access_levels, using: Entities::ProtectedRefAccess
    end

F
Felipe Artur 已提交
470 471
    class Milestone < Grape::Entity
      expose :id, :iid
F
Felipe Artur 已提交
472 473
      expose :project_id, if: -> (entity, options) { entity&.project_id }
      expose :group_id, if: -> (entity, options) { entity&.group_id }
F
Felipe Artur 已提交
474 475
      expose :title, :description
      expose :state, :created_at, :updated_at
476
      expose :due_date
V
Valery Sizov 已提交
477
      expose :start_date
478 479 480 481

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

484
    class IssueBasic < ProjectEntity
485
      expose :closed_at
H
haseeb 已提交
486
      expose :closed_by, using: Entities::UserBasic
487 488 489 490
      expose :labels do |issue, options|
        # Avoids an N+1 query since labels are preloaded
        issue.labels.map(&:title).sort
      end
491
      expose :milestone, using: Entities::Milestone
492 493 494 495 496
      expose :assignees, :author, using: Entities::UserBasic

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

Z
Z.J. van de Weg 已提交
498
      expose :user_notes_count
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
      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
515
      expose :due_date
516
      expose :confidential
517
      expose :discussion_locked
518 519 520 521

      expose :web_url do |issue, options|
        Gitlab::UrlBuilder.build(issue)
      end
522 523 524 525

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

528
    class Issue < IssueBasic
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
      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

549 550 551 552 553
      expose :subscribed do |issue, options|
        issue.subscribed?(options[:current_user], options[:project] || issue.project)
      end
    end

554
    class IssuableTimeStats < Grape::Entity
555 556 557 558
      format_with(:time_tracking_formatter) do |time_spent|
        Gitlab::TimeTrackingFormatter.output(time_spent)
      end

559 560 561
      expose :time_estimate
      expose :total_time_spent
      expose :human_time_estimate
562 563 564 565 566

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

567
      # rubocop: disable CodeReuse/ActiveRecord
568 569 570 571
      def total_time_spent
        # Avoids an N+1 query since timelogs are preloaded
        object.timelogs.map(&:time_spent).sum
      end
572
      # rubocop: enable CodeReuse/ActiveRecord
573 574
    end

575 576 577 578 579
    class ExternalIssue < Grape::Entity
      expose :title
      expose :id
    end

H
haseeb 已提交
580 581
    class PipelineBasic < Grape::Entity
      expose :id, :sha, :ref, :status
582 583 584 585

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

S
Stan Hu 已提交
588 589 590 591 592 593 594
    class MergeRequestSimple < ProjectEntity
      expose :title
      expose :web_url do |merge_request, options|
        Gitlab::UrlBuilder.build(merge_request)
      end
    end

595
    class MergeRequestBasic < ProjectEntity
596
      expose :title_html, if: -> (_, options) { options[:render_html] } do |entity|
P
Phil Hughes 已提交
597
        MarkupHelper.markdown_field(entity, :title)
598 599
      end
      expose :description_html, if: -> (_, options) { options[:render_html] } do |entity|
P
Phil Hughes 已提交
600
        MarkupHelper.markdown_field(entity, :description)
601
      end
V
Valery Sizov 已提交
602
      expose :target_branch, :source_branch
603 604 605 606 607 608 609 610 611 612 613 614 615 616
      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
617 618
      expose :author, :assignee, using: Entities::UserBasic
      expose :source_project_id, :target_project_id
619 620 621 622
      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 已提交
623
      expose :work_in_progress?, as: :work_in_progress
624
      expose :milestone, using: Entities::Milestone
J
James Lopez 已提交
625
      expose :merge_when_pipeline_succeeds
626 627 628 629 630 631

      # 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|
632 633
        merge_request.check_if_can_be_merged
        merge_request.merge_status
634
      end
635 636
      expose :diff_head_sha, as: :sha
      expose :merge_commit_sha
Z
Z.J. van de Weg 已提交
637
      expose :user_notes_count
638
      expose :discussion_locked
639 640
      expose :should_remove_source_branch?, as: :should_remove_source_branch
      expose :force_remove_source_branch?, as: :force_remove_source_branch
641 642 643
      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? }
644 645 646 647

      expose :web_url do |merge_request, options|
        Gitlab::UrlBuilder.build(merge_request)
      end
648 649 650 651

      expose :time_stats, using: 'API::Entities::IssuableTimeStats' do |merge_request|
        merge_request
      end
652 653

      expose :squash
A
Alex Denisov 已提交
654
    end
V
Valeriy Sizov 已提交
655

656 657 658 659
    class MergeRequest < MergeRequestBasic
      expose :subscribed do |merge_request, options|
        merge_request.subscribed?(options[:current_user], options[:project])
      end
660 661 662 663

      expose :changes_count do |merge_request, _options|
        merge_request.merge_request_diff.real_size
      end
H
haseeb 已提交
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696

      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

697 698
      expose :diff_refs, using: Entities::DiffRefs

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

H
haseeb 已提交
701 702 703
      def build_available?(options)
        options[:project]&.feature_available?(:builds, options[:current_user])
      end
704 705
    end

706
    class MergeRequestChanges < MergeRequest
707
      expose :diffs, as: :changes, using: Entities::Diff do |compare, _|
D
Douwe Maan 已提交
708
        compare.raw_diffs(limits: false).to_a
709 710 711
      end
    end

712 713 714
    class MergeRequestDiff < Grape::Entity
      expose :id, :head_commit_sha, :base_commit_sha, :start_commit_sha,
        :created_at, :merge_request_id, :state, :real_size
715
    end
716

717
    class MergeRequestDiffFull < MergeRequestDiff
718
      expose :commits, using: Entities::Commit
719

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

725
    class SSHKey < Grape::Entity
726
      expose :id, :title, :key, :created_at
V
Valeriy Sizov 已提交
727
    end
728

729
    class SSHKeyWithUser < SSHKey
730
      expose :user, using: Entities::UserPublic
731 732
    end

733 734 735 736 737
    class DeployKeysProject < Grape::Entity
      expose :deploy_key, merge: true, using: Entities::SSHKey
      expose :can_push
    end

R
Robert Schilling 已提交
738 739 740 741
    class GPGKey < Grape::Entity
      expose :id, :key, :created_at
    end

742 743 744 745 746
    class DiffPosition < Grape::Entity
      expose :base_sha, :start_sha, :head_sha, :old_path, :new_path,
        :position_type
    end

747
    class Note < Grape::Entity
S
sue445 已提交
748 749 750
      # Only Issue and MergeRequest have iid
      NOTEABLE_TYPES_WITH_IID = %w(Issue MergeRequest).freeze

751
      expose :id
J
Jan Provaznik 已提交
752
      expose :type
753
      expose :note, as: :body
754
      expose :attachment_identifier, as: :attachment
755
      expose :author, using: Entities::UserBasic
756
      expose :created_at, :updated_at
757
      expose :system?, as: :system
D
Dmitriy Zaporozhets 已提交
758
      expose :noteable_id, :noteable_type
S
sue445 已提交
759

760
      expose :position, if: ->(note, options) { note.is_a?(DiffNote) } do |note|
761 762 763 764 765 766 767
        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 已提交
768 769
      # Avoid N+1 queries as much as possible
      expose(:noteable_iid) { |note| note.noteable.iid if NOTEABLE_TYPES_WITH_IID.include?(note.noteable_type) }
770
    end
771

J
Jan Provaznik 已提交
772 773 774 775 776 777
    class Discussion < Grape::Entity
      expose :id
      expose :individual_note?, as: :individual_note
      expose :notes, using: Entities::Note
    end

I
Imre 已提交
778 779 780 781 782 783
    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 已提交
784 785 786 787 788 789 790 791
    class AwardEmoji < Grape::Entity
      expose :id
      expose :name
      expose :user, using: Entities::UserBasic
      expose :created_at, :updated_at
      expose :awardable_id, :awardable_type
    end

792 793 794 795
    class MRNote < Grape::Entity
      expose :note
      expose :author, using: Entities::UserBasic
    end
D
Dmitriy Zaporozhets 已提交
796

797 798
    class CommitNote < Grape::Entity
      expose :note
799 800 801
      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? }
802
      expose :author, using: Entities::UserBasic
803
      expose :created_at
804 805
    end

K
Kamil Trzcinski 已提交
806 807
    class CommitStatus < Grape::Entity
      expose :id, :sha, :ref, :status, :name, :target_url, :description,
808
             :created_at, :started_at, :finished_at, :allow_failure, :coverage
K
Kamil Trzcinski 已提交
809
      expose :author, using: Entities::UserBasic
K
Kamil Trzcinski 已提交
810 811
    end

812 813 814 815 816
    class PushEventPayload < Grape::Entity
      expose :commit_count, :action, :ref_type, :commit_from, :commit_to
      expose :ref, :commit_title
    end

D
Dmitriy Zaporozhets 已提交
817
    class Event < Grape::Entity
818
      expose :project_id, :action_name
S
sue445 已提交
819
      expose :target_id, :target_iid, :target_type, :author_id
820
      expose :target_title
821
      expose :created_at
D
Dmitriy Zaporozhets 已提交
822 823
      expose :note, using: Entities::Note, if: ->(event, options) { event.note? }
      expose :author, using: Entities::UserBasic, if: ->(event, options) { event.author }
824

825 826 827 828 829
      expose :push_event_payload,
        as: :push_data,
        using: PushEventPayload,
        if: -> (event, _) { event.push? }

830
      expose :author_username do |event, options|
Z
Z.J. van de Weg 已提交
831
        event.author&.username
832
      end
D
Dmitriy Zaporozhets 已提交
833
    end
834

835
    class ProjectGroupLink < Grape::Entity
836
      expose :id, :project_id, :group_id, :group_access, :expires_at
837 838
    end

D
Douglas Barbosa Alexandre 已提交
839 840
    class Todo < Grape::Entity
      expose :id
841 842
      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 已提交
843
      expose :author, using: Entities::UserBasic
R
Robert Schilling 已提交
844
      expose :action_name
D
Douglas Barbosa Alexandre 已提交
845
      expose :target_type
846 847

      expose :target do |todo, options|
848
        todo_target_class(todo.target_type).represent(todo.target, options)
D
Douglas Barbosa Alexandre 已提交
849 850 851 852
      end

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

856 857
        Gitlab::Routing
          .url_helpers
858
          .public_send(target_url, todo.parent, todo.target, anchor: target_anchor) # rubocop:disable GitlabSecurity/PublicSend
D
Douglas Barbosa Alexandre 已提交
859 860 861 862 863
      end

      expose :body
      expose :state
      expose :created_at
864 865 866 867

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

870
    class NamespaceBasic < Grape::Entity
871
      expose :id, :name, :path, :kind, :full_path, :parent_id
872
    end
873

874
    class Namespace < NamespaceBasic
875 876 877 878 879 880
      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)
881
      end
882
    end
883

884
    class MemberAccess < Grape::Entity
D
Dmitriy Zaporozhets 已提交
885
      expose :access_level
886
      expose :notification_level do |member, options|
887 888 889
        if member.notification_setting
          ::NotificationSetting.levels[member.notification_setting.level]
        end
890
      end
891 892
    end

893
    class ProjectAccess < MemberAccess
894 895
    end

896
    class GroupAccess < MemberAccess
897 898
    end

899 900 901
    class NotificationSetting < Grape::Entity
      expose :level
      expose :events, if: ->(notification_setting, _) { notification_setting.custom? } do
902
        ::NotificationSetting.email_events.each do |event|
903 904 905 906 907 908 909 910 911 912 913
          expose event
        end
      end
    end

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

914 915
    class ProjectService < Grape::Entity
      expose :id, :title, :created_at, :updated_at, :active
916 917
      expose :push_events, :issues_events, :confidential_issues_events
      expose :merge_requests_events, :tag_push_events, :note_events
918
      expose :confidential_note_events, :pipeline_events, :wiki_page_events
919
      expose :job_events
920 921
      # Expose serialized properties
      expose :properties do |service, options|
S
Stan Hu 已提交
922
        service.properties.slice(*service.api_field_names)
923 924 925
      end
    end

926 927 928
    class ProjectWithAccess < Project
      expose :permissions do
        expose :project_access, using: Entities::ProjectAccess do |project, options|
929 930
          if options[:project_members]
            options[:project_members].find { |member| member.source_id == project.id }
931 932
          else
            project.project_member(options[:current_user])
933
          end
934 935 936
        end

        expose :group_access, using: Entities::GroupAccess do |project, options|
937
          if project.group
938 939
            if options[:group_members]
              options[:group_members].find { |member| member.source_id == project.namespace_id }
940 941
            else
              project.group.group_member(options[:current_user])
942
            end
943
          end
944 945
        end
      end
946

947
      # rubocop: disable CodeReuse/ActiveRecord
948 949 950
      def self.preload_relation(projects_relation, options = {})
        relation = super(projects_relation, options)

951 952 953 954 955 956 957
        # 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)
958 959
        end

960 961 962 963 964 965 966 967 968
        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])
969 970 971

        relation
      end
972
      # rubocop: enable CodeReuse/ActiveRecord
973
    end
974

A
Andre Guedes 已提交
975
    class LabelBasic < Grape::Entity
R
Rares Sfirlogea 已提交
976
      expose :id, :name, :color, :description
A
Andre Guedes 已提交
977 978 979
    end

    class Label < LabelBasic
980
      expose :open_issues_count do |label, options|
F
Francesco Coda Zabetta 已提交
981 982
        label.open_issues_count(options[:current_user])
      end
983

F
Francesco Coda Zabetta 已提交
984 985 986
      expose :closed_issues_count do |label, options|
        label.closed_issues_count(options[:current_user])
      end
987

F
Francesco Coda Zabetta 已提交
988 989
      expose :open_merge_requests_count do |label, options|
        label.open_merge_requests_count(options[:current_user])
990 991
      end

992 993 994
      expose :priority do |label, options|
        label.priority(options[:project])
      end
995 996

      expose :subscribed do |label, options|
997
        label.subscribed?(options[:current_user], options[:project])
998
      end
999
    end
1000

A
Andre Guedes 已提交
1001 1002 1003 1004 1005 1006 1007 1008
    class List < Grape::Entity
      expose :id
      expose :label, using: Entities::LabelBasic
      expose :position
    end

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

A
Andre Guedes 已提交
1011 1012 1013 1014 1015
      expose :lists, using: Entities::List do |board|
        board.lists.destroyable
      end
    end

1016
    class Compare < Grape::Entity
1017 1018
      expose :commit, using: Entities::Commit do |compare, options|
        ::Commit.decorate(compare.commits, nil).last
1019
      end
1020

1021 1022
      expose :commits, using: Entities::Commit do |compare, options|
        ::Commit.decorate(compare.commits, nil)
1023
      end
1024

1025
      expose :diffs, using: Entities::Diff do |compare, options|
D
Douwe Maan 已提交
1026
        compare.diffs(limits: false).to_a
1027
      end
1028 1029

      expose :compare_timeout do |compare, options|
J
Jacob Vosmaer 已提交
1030
        compare.diffs.overflow?
1031 1032 1033
      end

      expose :same, as: :compare_same_ref
1034
    end
1035 1036 1037 1038

    class Contributor < Grape::Entity
      expose :name, :email, :commits, :additions, :deletions
    end
D
Douwe Maan 已提交
1039 1040 1041 1042

    class BroadcastMessage < Grape::Entity
      expose :message, :starts_at, :ends_at, :color, :font
    end
1043 1044

    class ApplicationSetting < Grape::Entity
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
      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)
1055 1056 1057 1058 1059 1060
      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) }
1061 1062 1063 1064

      # 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
1065
    end
D
Dmitriy Zaporozhets 已提交
1066 1067

    class Release < Grape::Entity
1068 1069
      expose :tag, as: :tag_name
      expose :description
D
Dmitriy Zaporozhets 已提交
1070
    end
1071

R
Robert Schilling 已提交
1072
    class Tag < Grape::Entity
1073
      expose :name, :message, :target
1074

1075
      expose :commit, using: Entities::Commit do |repo_tag, options|
1076
        options[:project].repository.commit(repo_tag.dereferenced_target)
1077 1078
      end

1079
      # rubocop: disable CodeReuse/ActiveRecord
1080 1081
      expose :release, using: Entities::Release do |repo_tag, options|
        options[:project].releases.find_by(tag: repo_tag.name)
1082
      end
1083
      # rubocop: enable CodeReuse/ActiveRecord
1084
    end
K
Kamil Trzcinski 已提交
1085

T
Tomasz Maczukin 已提交
1086
    class Runner < Grape::Entity
T
Tomasz Maczukin 已提交
1087 1088
      expose :id
      expose :description
1089
      expose :ip_address
T
Tomasz Maczukin 已提交
1090
      expose :active
1091
      expose :instance_type?, as: :is_shared
T
Tomasz Maczukin 已提交
1092
      expose :name
1093
      expose :online?, as: :online
1094
      expose :status
T
Tomasz Maczukin 已提交
1095 1096
    end

1097 1098
    class RunnerDetails < Runner
      expose :tag_list
1099
      expose :run_untagged
1100
      expose :locked
1101
      expose :maximum_timeout
S
Shinya Maeda 已提交
1102
      expose :access_level
1103
      expose :version, :revision, :platform, :architecture
1104
      expose :contacted_at
1105
      expose :token, if: lambda { |runner, options| options[:current_user].admin? || !runner.instance_type? }
1106
      # rubocop: disable CodeReuse/ActiveRecord
1107
      expose :projects, with: Entities::BasicProjectDetails do |runner, options|
B
blackst0ne 已提交
1108
        if options[:current_user].admin?
1109 1110
          runner.projects
        else
1111
          options[:current_user].authorized_projects.where(id: runner.projects)
1112 1113
        end
      end
1114 1115
      # rubocop: enable CodeReuse/ActiveRecord
      # rubocop: disable CodeReuse/ActiveRecord
1116 1117 1118 1119 1120 1121 1122
      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
1123
      # rubocop: enable CodeReuse/ActiveRecord
1124 1125
    end

1126 1127 1128 1129
    class RunnerRegistrationDetails < Grape::Entity
      expose :id, :token
    end

1130
    class JobArtifactFile < Grape::Entity
1131 1132 1133
      expose :filename, :size
    end

1134 1135 1136 1137
    class JobArtifact < Grape::Entity
      expose :file_type, :size, :filename, :file_format
    end

T
Tomasz Maczukin 已提交
1138
    class JobBasic < Grape::Entity
T
Tomasz Maczukin 已提交
1139
      expose :id, :status, :stage, :name, :ref, :tag, :coverage
T
Tomasz Maczukin 已提交
1140
      expose :created_at, :started_at, :finished_at
M
Mehdi Lahmam 已提交
1141
      expose :duration
T
Tomasz Maczukin 已提交
1142
      expose :user, with: User
1143
      expose :commit, with: Commit
1144
      expose :pipeline, with: PipelineBasic
1145 1146 1147 1148

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

T
Tomasz Maczukin 已提交
1151
    class Job < JobBasic
1152
      # artifacts_file is included in job_artifacts, but kept for backward compatibility (remove in api/v5)
T
Tomasz Maczukin 已提交
1153
      expose :artifacts_file, using: JobArtifactFile, if: -> (job, opts) { job.artifacts? }
1154
      expose :job_artifacts, as: :artifacts, using: JobArtifact
T
Tomasz Maczukin 已提交
1155
      expose :runner, with: Runner
1156
      expose :artifacts_expire_at
T
Tomasz Maczukin 已提交
1157 1158 1159
    end

    class JobBasicWithProject < JobBasic
T
Tomasz Maczukin 已提交
1160 1161 1162
      expose :project, with: ProjectIdentity
    end

T
Tomasz Maczukin 已提交
1163
    class Trigger < Grape::Entity
1164
      expose :id
1165
      expose :token, :description
1166
      expose :created_at, :updated_at, :last_used
1167
      expose :owner, using: Entities::UserBasic
T
Tomasz Maczukin 已提交
1168
    end
1169

1170
    class Variable < Grape::Entity
T
Tomasz Maczukin 已提交
1171
      expose :key, :value
S
Shinya Maeda 已提交
1172
      expose :protected?, as: :protected, if: -> (entity, _) { entity.respond_to?(:protected?) }
1173
    end
1174

1175 1176
    class Pipeline < PipelineBasic
      expose :before_sha, :tag, :yaml_errors
Z
Z.J. van de Weg 已提交
1177 1178 1179 1180

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

1184 1185 1186
    class PipelineSchedule < Grape::Entity
      expose :id
      expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active
1187
      expose :created_at, :updated_at
1188 1189 1190
      expose :owner, using: Entities::UserBasic
    end

S
Shinya Maeda 已提交
1191 1192
    class PipelineScheduleDetails < PipelineSchedule
      expose :last_pipeline, using: Entities::PipelineBasic
1193
      expose :variables, using: Entities::Variable
S
Shinya Maeda 已提交
1194 1195
    end

1196
    class EnvironmentBasic < Grape::Entity
N
Nick Thomas 已提交
1197
      expose :id, :name, :slug, :external_url
1198 1199
    end

1200
    class Environment < EnvironmentBasic
1201
      expose :project, using: Entities::BasicProjectDetails
Z
Z.J. van de Weg 已提交
1202 1203 1204 1205
    end

    class Deployment < Grape::Entity
      expose :id, :iid, :ref, :sha, :created_at
1206 1207
      expose :user,        using: Entities::UserBasic
      expose :environment, using: Entities::EnvironmentBasic
1208
      expose :deployable,  using: Entities::Job
1209 1210
    end

1211
    class License < Grape::Entity
1212
      expose :key, :name, :nickname
1213
      expose :popular?, as: :popular
1214 1215 1216
      expose :url, as: :html_url
      expose(:source_url) { |license| license.meta['source'] }
      expose(:description) { |license| license.meta['description'] }
1217 1218 1219
      expose(:conditions) { |license| license.meta['conditions'] }
      expose(:permissions) { |license| license.meta['permissions'] }
      expose(:limitations) { |license| license.meta['limitations'] }
1220 1221
      expose :content
    end
1222

Z
ZJ van de Weg 已提交
1223
    class TemplatesList < Grape::Entity
N
Nick Thomas 已提交
1224
      expose :key
1225 1226 1227
      expose :name
    end

Z
ZJ van de Weg 已提交
1228
    class Template < Grape::Entity
1229 1230
      expose :name, :content
    end
1231 1232 1233 1234 1235

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

1237
    class PersonalAccessToken < Grape::Entity
1238 1239 1240 1241 1242 1243 1244
      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

1245
    class PersonalAccessTokenWithToken < PersonalAccessToken
1246 1247
      expose :token
    end
1248 1249 1250 1251

    class ImpersonationToken < PersonalAccessTokenWithToken
      expose :impersonation
    end
1252

1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
    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

1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290
    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 已提交
1291

1292
      class RunnerInfo < Grape::Entity
T
Tomasz Maczukin 已提交
1293
        expose :metadata_timeout, as: :timeout
F
Francisco Javier López 已提交
1294
        expose :runner_session_url
1295
      end
T
Tomasz Maczukin 已提交
1296

1297
      class Step < Grape::Entity
T
Tomasz Maczukin 已提交
1298
        expose :name, :script, :timeout, :when, :allow_failure
1299
      end
T
Tomasz Maczukin 已提交
1300

1301
      class Image < Grape::Entity
1302 1303 1304
        expose :name, :entrypoint
      end

1305
      class Service < Image
1306
        expose :alias, :command
1307
      end
T
Tomasz Maczukin 已提交
1308

1309
      class Artifacts < Grape::Entity
S
Shinya Maeda 已提交
1310 1311 1312 1313 1314 1315 1316
        expose :name
        expose :untracked
        expose :paths
        expose :when
        expose :expire_in
        expose :artifact_type
        expose :artifact_format
T
Tomasz Maczukin 已提交
1317 1318
      end

1319
      class Cache < Grape::Entity
1320
        expose :key, :untracked, :paths, :policy
T
Tomasz Maczukin 已提交
1321 1322
      end

1323 1324 1325
      class Credentials < Grape::Entity
        expose :type, :url, :username, :password
      end
T
Tomasz Maczukin 已提交
1326

1327
      class Dependency < Grape::Entity
T
Tomasz Maczukin 已提交
1328
        expose :id, :name, :token
1329
        expose :artifacts_file, using: JobArtifactFile, if: ->(job, _) { job.artifacts? }
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351
      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
1352
        expose :services, using: Service
1353 1354 1355
        expose :artifacts, using: Artifacts
        expose :cache, using: Cache
        expose :credentials, using: Credentials
T
Tomasz Maczukin 已提交
1356
        expose :dependencies, using: Dependency
1357
        expose :features
1358
      end
T
Tomasz Maczukin 已提交
1359
    end
1360 1361 1362 1363

    class UserAgentDetail < Grape::Entity
      expose :user_agent
      expose :ip_address
J
James Lopez 已提交
1364
      expose :submitted, as: :akismet_submitted
1365
    end
1366

1367 1368 1369 1370
    class CustomAttribute < Grape::Entity
      expose :key
      expose :value
    end
T
Travis Miller 已提交
1371

1372 1373 1374 1375 1376
    class PagesDomainCertificateExpiration < Grape::Entity
      expose :expired?, as: :expired
      expose :expiration
    end

T
Travis Miller 已提交
1377 1378 1379 1380 1381 1382 1383
    class PagesDomainCertificate < Grape::Entity
      expose :subject
      expose :expired?, as: :expired
      expose :certificate
      expose :certificate_text
    end

1384 1385 1386
    class PagesDomainBasic < Grape::Entity
      expose :domain
      expose :url
1387
      expose :project_id
1388 1389 1390 1391
      expose :verified?, as: :verified
      expose :verification_code, as: :verification_code
      expose :enabled_until

1392 1393 1394 1395 1396 1397 1398 1399
      expose :certificate,
        as: :certificate_expiration,
        if: ->(pages_domain, _) { pages_domain.certificate? },
        using: PagesDomainCertificateExpiration do |pages_domain|
        pages_domain
      end
    end

T
Travis Miller 已提交
1400 1401 1402
    class PagesDomain < Grape::Entity
      expose :domain
      expose :url
1403 1404 1405 1406
      expose :verified?, as: :verified
      expose :verification_code, as: :verification_code
      expose :enabled_until

T
Travis Miller 已提交
1407
      expose :certificate,
1408 1409
        if: ->(pages_domain, _) { pages_domain.certificate? },
        using: PagesDomainCertificate do |pages_domain|
T
Travis Miller 已提交
1410 1411 1412
        pages_domain
      end
    end
N
Nicolas MERELLI 已提交
1413 1414 1415 1416 1417

    class Application < Grape::Entity
      expose :uid, as: :application_id
      expose :redirect_uri, as: :callback_url
    end
1418 1419 1420 1421 1422

    # Use with care, this exposes the secret
    class ApplicationWithSecret < Application
      expose :secret
    end
J
Jarka Kadlecová 已提交
1423 1424 1425 1426 1427 1428 1429 1430

    class Blob < Grape::Entity
      expose :basename
      expose :data
      expose :filename
      expose :id
      expose :ref
      expose :startline
1431
      expose :project_id
J
Jarka Kadlecová 已提交
1432
    end
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450

    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
1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464

    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 已提交
1465 1466
  end
end