entities.rb 29.5 KB
Newer Older
1
module API
Nihad Abbasov's avatar
Nihad Abbasov committed
2
  module Entities
3 4 5
    class UserSafe < Grape::Entity
      expose :name, :username
    end
6

7
    class UserBasic < UserSafe
8 9 10 11
      expose :id, :state
      expose :avatar_url do |user, options|
        user.avatar_url(only_path: false)
      end
Douwe Maan's avatar
Douwe Maan committed
12 13

      expose :web_url do |user, options|
14
        Gitlab::Routing.url_helpers.user_url(user)
Douwe Maan's avatar
Douwe Maan committed
15
      end
Nihad Abbasov's avatar
Nihad Abbasov committed
16
    end
Nihad Abbasov's avatar
Nihad Abbasov committed
17

18 19
    class User < UserBasic
      expose :created_at
20
      expose :bio, :location, :skype, :linkedin, :twitter, :website_url, :organization
21 22
    end

23 24
    class UserActivity < Grape::Entity
      expose :username
25 26
      expose :last_activity_on
      expose :last_activity_on, as: :last_activity_at # Back-compat
27 28
    end

29 30 31 32
    class Identity < Grape::Entity
      expose :provider, :extern_uid
    end

33
    class UserPublic < User
34 35
      expose :last_sign_in_at
      expose :confirmed_at
36
      expose :last_activity_on
37
      expose :email
38
      expose :color_scheme_id, :projects_limit, :current_sign_in_at
39
      expose :identities, using: Entities::Identity
40 41
      expose :can_create_group?, as: :can_create_group
      expose :can_create_project?, as: :can_create_project
42
      expose :two_factor_enabled?, as: :two_factor_enabled
43
      expose :external
44 45
    end

46
    class UserWithAdmin < UserPublic
47
      expose :admin?, as: :is_admin
48 49
    end

50 51 52 53
    class UserWithPrivateDetails < UserWithAdmin
      expose :private_token
    end

54 55 56 57
    class Email < Grape::Entity
      expose :id, :email
    end

miks's avatar
miks committed
58
    class Hook < Grape::Entity
59
      expose :id, :url, :created_at, :push_events, :tag_push_events, :repository_update_events
60
      expose :enable_ssl_verification
miks's avatar
miks committed
61 62
    end

63
    class ProjectHook < Hook
64
      expose :project_id, :issues_events, :merge_requests_events
65
      expose :note_events, :pipeline_events, :wiki_page_events
66
      expose :job_events
67 68
    end

69 70 71 72 73 74 75 76
    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
    end

77 78 79 80 81 82 83 84 85 86
    class BasicProjectDetails < Grape::Entity
      expose :id, :description, :default_branch, :tag_list
      expose :ssh_url_to_repo, :http_url_to_repo, :web_url
      expose :name, :name_with_namespace
      expose :path, :path_with_namespace
      expose :star_count, :forks_count
      expose :created_at, :last_activity_at
    end

    class Project < BasicProjectDetails 
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
      include ::API::Helpers::RelatedResourcesHelpers

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

        expose :issues, if: -> (*args) { issues_available?(*args) } do |project|
          expose_url(api_v4_projects_issues_path(id: project.id))
        end

        expose :merge_requests, if: -> (*args) { mrs_available?(*args) } do |project|
          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

119
      expose :archived?, as: :archived
120
      expose :visibility
121
      expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
122 123 124
      expose :container_registry_enabled

      # Expose old field names with the new permissions methods to keep API compatible
125 126 127
      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]) }
128
      expose(:jobs_enabled) { |project, options| project.feature_available?(:builds, options[:current_user]) }
129
      expose(:snippets_enabled) { |project, options| project.feature_available?(:snippets, options[:current_user]) }
130

131 132
      expose :shared_runners_enabled
      expose :lfs_enabled?, as: :lfs_enabled
133
      expose :creator_id
134
      expose :namespace, using: 'API::Entities::Namespace'
135
      expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda{ |project, options| project.forked? }
136 137
      expose :import_status
      expose :import_error, if: lambda { |_project, options| options[:user_can_admin_project] }
138 139 140
      expose :avatar_url do |user, options|
        user.avatar_url(only_path: false)
      end
141
      expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:current_user]) }
142
      expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
143
      expose :public_builds, as: :public_jobs
144
      expose :ci_config_path
145 146 147
      expose :shared_with_groups do |project, options|
        SharedGroup.represent(project.project_group_links.all, options)
      end
148
      expose :only_allow_merge_if_pipeline_succeeds
149
      expose :request_access_enabled
150
      expose :only_allow_merge_if_all_discussions_are_resolved
151
      expose :printing_merge_request_link_enabled
152 153 154 155 156 157 158 159 160

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

    class ProjectStatistics < Grape::Entity
      expose :commit_count
      expose :storage_size
      expose :repository_size
      expose :lfs_objects_size
161
      expose :build_artifacts_size, as: :job_artifacts_size
Nihad Abbasov's avatar
Nihad Abbasov committed
162 163
    end

164
    class Member < UserBasic
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
165
      expose :access_level do |user, options|
166
        member = options[:member] || options[:source].members.find_by(user_id: user.id)
167 168
        member.access_level
      end
169
      expose :expires_at do |user, options|
170
        member = options[:member] || options[:source].members.find_by(user_id: user.id)
171 172
        member.expires_at
      end
173 174 175 176
    end

    class AccessRequester < UserBasic
      expose :requested_at do |user, options|
177
        access_requester = options[:access_requester] || options[:source].requesters.find_by(user_id: user.id)
178
        access_requester.requested_at
179
      end
miks's avatar
miks committed
180 181
    end

182
    class Group < Grape::Entity
183
      expose :id, :name, :path, :description, :visibility
184
      expose :lfs_enabled?, as: :lfs_enabled
185 186 187
      expose :avatar_url do |user, options|
        user.avatar_url(only_path: false)
      end
188
      expose :web_url
189
      expose :request_access_enabled
190
      expose :full_name, :full_path
191 192 193 194

      if ::Group.supports_nested_groups?
        expose :parent_id
      end
195 196 197 198 199 200

      expose :statistics, if: :statistics do
        with_options format_with: -> (value) { value.to_i } do
          expose :storage_size
          expose :repository_size
          expose :lfs_objects_size
201
          expose :build_artifacts_size, as: :job_artifacts_size
202 203
        end
      end
204
    end
Andrew8xx8's avatar
Andrew8xx8 committed
205

206
    class GroupDetail < Group
207
      expose :projects, using: Entities::Project
208
      expose :shared_projects, using: Entities::Project
209 210
    end

211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
    class RepoCommit < Grape::Entity
      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

    class RepoCommitStats < Grape::Entity
      expose :additions, :deletions, :total
    end

    class RepoCommitDetail < RepoCommit
      expose :stats, using: Entities::RepoCommitStats
      expose :status
    end

228
    class RepoBranch < Grape::Entity
229 230
      expose :name

231
      expose :commit, using: Entities::RepoCommit do |repo_branch, options|
232
        options[:project].repository.commit(repo_branch.dereferenced_target)
233 234
      end

235 236 237 238
      expose :merged do |repo_branch, options|
        options[:project].repository.merged_to_root_ref?(repo_branch.name)
      end

239
      expose :protected do |repo_branch, options|
240
        ::ProtectedBranch.protected?(options[:project], repo_branch.name)
241 242
      end

243
      expose :developers_can_push do |repo_branch, options|
244
        options[:project].protected_branches.developers_can?(:push, repo_branch.name)
245
      end
246

247
      expose :developers_can_merge do |repo_branch, options|
248
        options[:project].protected_branches.developers_can?(:merge, repo_branch.name)
249
      end
Nihad Abbasov's avatar
Nihad Abbasov committed
250
    end
Nihad Abbasov's avatar
Nihad Abbasov committed
251

252
    class RepoTreeObject < Grape::Entity
253
      expose :id, :name, :type, :path
254 255

      expose :mode do |obj, options|
256
        filemode = obj.mode
257 258 259 260 261
        filemode = "0" + filemode if filemode.length < 6
        filemode
      end
    end

Nihad Abbasov's avatar
Nihad Abbasov committed
262
    class ProjectSnippet < Grape::Entity
263
      expose :id, :title, :file_name, :description
264
      expose :author, using: Entities::UserBasic
265
      expose :updated_at, :created_at
266

267 268 269
      expose :web_url do |snippet, options|
        Gitlab::UrlBuilder.build(snippet)
      end
Nihad Abbasov's avatar
Nihad Abbasov committed
270
    end
Nihad Abbasov's avatar
Nihad Abbasov committed
271

272
    class PersonalSnippet < Grape::Entity
273
      expose :id, :title, :file_name, :description
274 275 276 277 278 279 280 281 282 283 284
      expose :author, using: Entities::UserBasic
      expose :updated_at, :created_at

      expose :web_url do |snippet|
        Gitlab::UrlBuilder.build(snippet)
      end
      expose :raw_url do |snippet|
        Gitlab::UrlBuilder.build(snippet) + "/raw"
      end
    end

285 286
    class ProjectEntity < Grape::Entity
      expose :id, :iid
Felipe Artur's avatar
Felipe Artur committed
287
      expose(:project_id) { |entity| entity&.project.try(:id) }
288 289
      expose :title, :description
      expose :state, :created_at, :updated_at
290 291
    end

292 293
    class RepoDiff < Grape::Entity
      expose :old_path, :new_path, :a_mode, :b_mode, :diff
294 295 296
      expose :new_file?, as: :new_file
      expose :renamed_file?, as: :renamed_file
      expose :deleted_file?, as: :deleted_file
297 298
    end

299 300 301 302 303 304 305 306 307 308 309 310 311
    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

Felipe Artur's avatar
Felipe Artur committed
312 313
    class Milestone < Grape::Entity
      expose :id, :iid
314 315
      expose :project_id, if: -> (entity, options) { entity&.project_id }
      expose :group_id, if: -> (entity, options) { entity&.group_id }
Felipe Artur's avatar
Felipe Artur committed
316 317
      expose :title, :description
      expose :state, :created_at, :updated_at
318
      expose :due_date
319
      expose :start_date
Nihad Abbasov's avatar
Nihad Abbasov committed
320 321
    end

322
    class IssueBasic < ProjectEntity
323
      expose :label_names, as: :labels
324
      expose :milestone, using: Entities::Milestone
325 326 327 328 329
      expose :assignees, :author, using: Entities::UserBasic

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

Z.J. van de Weg's avatar
Z.J. van de Weg committed
331
      expose :user_notes_count
332
      expose :upvotes, :downvotes
333
      expose :due_date
334
      expose :confidential
335 336 337 338

      expose :web_url do |issue, options|
        Gitlab::UrlBuilder.build(issue)
      end
Nihad Abbasov's avatar
Nihad Abbasov committed
339
    end
Alex Denisov's avatar
Alex Denisov committed
340

341
    class Issue < IssueBasic
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
      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

362 363 364 365 366
      expose :subscribed do |issue, options|
        issue.subscribed?(options[:current_user], options[:project] || issue.project)
      end
    end

367 368 369 370 371 372 373
    class IssuableTimeStats < Grape::Entity
      expose :time_estimate
      expose :total_time_spent
      expose :human_time_estimate
      expose :human_total_time_spent
    end

374 375 376 377 378
    class ExternalIssue < Grape::Entity
      expose :title
      expose :id
    end

379 380 381 382 383 384 385
    class MergeRequestSimple < ProjectEntity
      expose :title
      expose :web_url do |merge_request, options|
        Gitlab::UrlBuilder.build(merge_request)
      end
    end

386
    class MergeRequestBasic < ProjectEntity
Valery Sizov's avatar
Valery Sizov committed
387
      expose :target_branch, :source_branch
388 389 390 391 392 393 394 395 396 397 398 399 400 401
      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
402 403
      expose :author, :assignee, using: Entities::UserBasic
      expose :source_project_id, :target_project_id
404 405 406 407
      expose :labels do |merge_request, options|
        # Avoids an N+1 query since labels are preloaded
        merge_request.labels.map(&:title).sort
      end
408
      expose :work_in_progress?, as: :work_in_progress
409
      expose :milestone, using: Entities::Milestone
410
      expose :merge_when_pipeline_succeeds
411
      expose :merge_status
412 413
      expose :diff_head_sha, as: :sha
      expose :merge_commit_sha
Z.J. van de Weg's avatar
Z.J. van de Weg committed
414
      expose :user_notes_count
415 416
      expose :should_remove_source_branch?, as: :should_remove_source_branch
      expose :force_remove_source_branch?, as: :force_remove_source_branch
417 418 419 420

      expose :web_url do |merge_request, options|
        Gitlab::UrlBuilder.build(merge_request)
      end
Alex Denisov's avatar
Alex Denisov committed
421
    end
422

423 424 425 426 427 428
    class MergeRequest < MergeRequestBasic
      expose :subscribed do |merge_request, options|
        merge_request.subscribed?(options[:current_user], options[:project])
      end
    end

429 430
    class MergeRequestChanges < MergeRequest
      expose :diffs, as: :changes, using: Entities::RepoDiff do |compare, _|
Douwe Maan's avatar
Douwe Maan committed
431
        compare.raw_diffs(limits: false).to_a
432 433 434
      end
    end

435 436 437
    class MergeRequestDiff < Grape::Entity
      expose :id, :head_commit_sha, :base_commit_sha, :start_commit_sha,
        :created_at, :merge_request_id, :state, :real_size
438
    end
439

440
    class MergeRequestDiffFull < MergeRequestDiff
441 442 443
      expose :commits, using: Entities::RepoCommit

      expose :diffs, using: Entities::RepoDiff do |compare, _|
Douwe Maan's avatar
Douwe Maan committed
444
        compare.raw_diffs(limits: false).to_a
445 446 447
      end
    end

448
    class SSHKey < Grape::Entity
449
      expose :id, :title, :key, :created_at, :can_push
450
    end
451

452
    class SSHKeyWithUser < SSHKey
453
      expose :user, using: Entities::UserPublic
454 455
    end

456
    class Note < Grape::Entity
457 458
      expose :id
      expose :note, as: :body
459
      expose :attachment_identifier, as: :attachment
460
      expose :author, using: Entities::UserBasic
461
      expose :created_at, :updated_at
462
      expose :system?, as: :system
463
      expose :noteable_id, :noteable_type
464
    end
465

466 467 468 469 470 471 472 473
    class AwardEmoji < Grape::Entity
      expose :id
      expose :name
      expose :user, using: Entities::UserBasic
      expose :created_at, :updated_at
      expose :awardable_id, :awardable_type
    end

474 475 476 477
    class MRNote < Grape::Entity
      expose :note
      expose :author, using: Entities::UserBasic
    end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
478

479 480
    class CommitNote < Grape::Entity
      expose :note
481 482 483
      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? }
484
      expose :author, using: Entities::UserBasic
485
      expose :created_at
486 487
    end

488 489
    class CommitStatus < Grape::Entity
      expose :id, :sha, :ref, :status, :name, :target_url, :description,
490
             :created_at, :started_at, :finished_at, :allow_failure, :coverage
Kamil Trzcinski's avatar
Kamil Trzcinski committed
491
      expose :author, using: Entities::UserBasic
492 493
    end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
494 495
    class Event < Grape::Entity
      expose :title, :project_id, :action_name
sue445's avatar
sue445 committed
496
      expose :target_id, :target_iid, :target_type, :author_id
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
497
      expose :data, :target_title
498
      expose :created_at
499 500
      expose :note, using: Entities::Note, if: ->(event, options) { event.note? }
      expose :author, using: Entities::UserBasic, if: ->(event, options) { event.author }
501 502

      expose :author_username do |event, options|
503
        event.author&.username
504
      end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
505
    end
506

507
    class ProjectGroupLink < Grape::Entity
508
      expose :id, :project_id, :group_id, :group_access, :expires_at
509 510
    end

Douglas Barbosa Alexandre's avatar
Douglas Barbosa Alexandre committed
511 512 513 514
    class Todo < Grape::Entity
      expose :id
      expose :project, using: Entities::BasicProjectDetails
      expose :author, using: Entities::UserBasic
Robert Schilling's avatar
Robert Schilling committed
515
      expose :action_name
Douglas Barbosa Alexandre's avatar
Douglas Barbosa Alexandre committed
516
      expose :target_type
517 518

      expose :target do |todo, options|
519 520
        target = todo.target_type == 'Commit' ? 'RepoCommit' : todo.target_type
        Entities.const_get(target).represent(todo.target, options)
Douglas Barbosa Alexandre's avatar
Douglas Barbosa Alexandre committed
521 522 523 524 525
      end

      expose :target_url do |todo, options|
        target_type   = todo.target_type.underscore
        target_url    = "namespace_project_#{target_type}_url"
526
        target_anchor = "note_#{todo.note_id}" if todo.note_id?
Douglas Barbosa Alexandre's avatar
Douglas Barbosa Alexandre committed
527

528
        Gitlab::Routing.url_helpers.public_send(target_url,
Douglas Barbosa Alexandre's avatar
Douglas Barbosa Alexandre committed
529 530 531 532 533 534 535 536
          todo.project.namespace, todo.project, todo.target, anchor: target_anchor)
      end

      expose :body
      expose :state
      expose :created_at
    end

537
    class Namespace < Grape::Entity
538 539
      expose :id, :name, :path, :kind, :full_path, :parent_id

540 541 542 543 544 545
      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)
546
      end
547
    end
548

549
    class MemberAccess < Grape::Entity
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
550
      expose :access_level
551 552
      expose :notification_level do |member, options|
        if member.notification_setting
553
          ::NotificationSetting.levels[member.notification_setting.level]
554 555
        end
      end
556 557
    end

558
    class ProjectAccess < MemberAccess
559 560
    end

561
    class GroupAccess < MemberAccess
562 563
    end

564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
    class NotificationSetting < Grape::Entity
      expose :level
      expose :events, if: ->(notification_setting, _) { notification_setting.custom? } do
        ::NotificationSetting::EMAIL_EVENTS.each do |event|
          expose event
        end
      end
    end

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

579 580
    class ProjectService < Grape::Entity
      expose :id, :title, :created_at, :updated_at, :active
581
      expose :push_events, :issues_events, :merge_requests_events
582
      expose :tag_push_events, :note_events, :pipeline_events
583
      expose :job_events
584 585
      # Expose serialized properties
      expose :properties do |service, options|
586 587 588
        field_names = service.fields
          .select { |field| options[:include_passwords] || field[:type] != 'password' }
          .map { |field| field[:name] }
589 590 591 592
        service.properties.slice(*field_names)
      end
    end

593 594 595
    class ProjectWithAccess < Project
      expose :permissions do
        expose :project_access, using: Entities::ProjectAccess do |project, options|
596 597 598 599 600
          if options.key?(:project_members)
            (options[:project_members] || []).find { |member| member.source_id == project.id }
          else
            project.project_members.find_by(user_id: options[:current_user].id)
          end
601 602 603
        end

        expose :group_access, using: Entities::GroupAccess do |project, options|
604
          if project.group
605 606 607 608 609
            if options.key?(:group_members)
              (options[:group_members] || []).find { |member| member.source_id == project.namespace_id }
            else
              project.group.group_members.find_by(user_id: options[:current_user].id)
            end
610
          end
611 612 613
        end
      end
    end
614

615
    class LabelBasic < Grape::Entity
Rares Sfirlogea's avatar
Rares Sfirlogea committed
616
      expose :id, :name, :color, :description
617 618 619
    end

    class Label < LabelBasic
620
      expose :open_issues_count do |label, options|
Francesco Coda Zabetta's avatar
Francesco Coda Zabetta committed
621 622
        label.open_issues_count(options[:current_user])
      end
623

Francesco Coda Zabetta's avatar
Francesco Coda Zabetta committed
624 625 626
      expose :closed_issues_count do |label, options|
        label.closed_issues_count(options[:current_user])
      end
627

Francesco Coda Zabetta's avatar
Francesco Coda Zabetta committed
628 629
      expose :open_merge_requests_count do |label, options|
        label.open_merge_requests_count(options[:current_user])
630 631
      end

632 633 634
      expose :priority do |label, options|
        label.priority(options[:project])
      end
635 636

      expose :subscribed do |label, options|
637
        label.subscribed?(options[:current_user], options[:project])
638
      end
639
    end
640

641 642 643 644 645 646 647 648 649 650 651 652 653
    class List < Grape::Entity
      expose :id
      expose :label, using: Entities::LabelBasic
      expose :position
    end

    class Board < Grape::Entity
      expose :id
      expose :lists, using: Entities::List do |board|
        board.lists.destroyable
      end
    end

654 655
    class Compare < Grape::Entity
      expose :commit, using: Entities::RepoCommit do |compare, options|
656
        Commit.decorate(compare.commits, nil).last
657
      end
658

659
      expose :commits, using: Entities::RepoCommit do |compare, options|
660
        Commit.decorate(compare.commits, nil)
661
      end
662

663
      expose :diffs, using: Entities::RepoDiff do |compare, options|
Douwe Maan's avatar
Douwe Maan committed
664
        compare.diffs(limits: false).to_a
665
      end
666 667

      expose :compare_timeout do |compare, options|
668
        compare.diffs.overflow?
669 670 671
      end

      expose :same, as: :compare_same_ref
672
    end
673 674 675 676

    class Contributor < Grape::Entity
      expose :name, :email, :commits, :additions, :deletions
    end
677 678 679 680

    class BroadcastMessage < Grape::Entity
      expose :message, :starts_at, :ends_at, :color, :font
    end
681 682 683

    class ApplicationSetting < Grape::Entity
      expose :id
684
      expose(*::ApplicationSettingsHelper.visible_attributes)
685 686 687 688 689 690
      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) }
691
      expose :password_authentication_enabled, as: :signin_enabled
692
    end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
693 694

    class Release < Grape::Entity
695 696
      expose :tag, as: :tag_name
      expose :description
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
697
    end
698 699

    class RepoTag < Grape::Entity
700
      expose :name, :message
701

702
      expose :commit do |repo_tag, options|
703
        options[:project].repository.commit(repo_tag.dereferenced_target)
704 705
      end

706 707
      expose :release, using: Entities::Release do |repo_tag, options|
        options[:project].releases.find_by(tag: repo_tag.name)
708 709
      end
    end
Kamil Trzcinski's avatar
Kamil Trzcinski committed
710

711
    class Runner < Grape::Entity
712 713 714 715 716 717 718
      expose :id
      expose :description
      expose :active
      expose :is_shared
      expose :name
    end

719 720
    class RunnerDetails < Runner
      expose :tag_list
721
      expose :run_untagged
722
      expose :locked
723
      expose :version, :revision, :platform, :architecture
724
      expose :contacted_at
725
      expose :token, if: lambda { |runner, options| options[:current_user].admin? || !runner.is_shared? }
726
      expose :projects, with: Entities::BasicProjectDetails do |runner, options|
727
        if options[:current_user].admin?
728 729
          runner.projects
        else
730
          options[:current_user].authorized_projects.where(id: runner.projects)
731 732
        end
      end
733 734
    end

735 736 737 738
    class RunnerRegistrationDetails < Grape::Entity
      expose :id, :token
    end

739
    class JobArtifactFile < Grape::Entity
740 741 742
      expose :filename, :size
    end

743 744 745 746
    class PipelineBasic < Grape::Entity
      expose :id, :sha, :ref, :status
    end

747
    class Job < Grape::Entity
748
      expose :id, :status, :stage, :name, :ref, :tag, :coverage
749
      expose :created_at, :started_at, :finished_at
Tomasz Maczukin's avatar
Tomasz Maczukin committed
750
      expose :user, with: User
Z.J. van de Weg's avatar
Z.J. van de Weg committed
751
      expose :artifacts_file, using: JobArtifactFile, if: -> (job, opts) { job.artifacts? }
752
      expose :commit, with: RepoCommit
753
      expose :runner, with: Runner
754
      expose :pipeline, with: PipelineBasic
755
    end
756

757
    class Trigger < Grape::Entity
758
      expose :id
759 760 761
      expose :token, :description
      expose :created_at, :updated_at, :deleted_at, :last_used
      expose :owner, using: Entities::UserBasic
762
    end
763

764
    class Variable < Grape::Entity
Tomasz Maczukin's avatar
Tomasz Maczukin committed
765
      expose :key, :value
766
      expose :protected?, as: :protected
767
    end
768

769 770
    class Pipeline < PipelineBasic
      expose :before_sha, :tag, :yaml_errors
771 772 773 774

      expose :user, with: Entities::UserBasic
      expose :created_at, :updated_at, :started_at, :finished_at, :committed_at
      expose :duration
775
      expose :coverage
776 777
    end

778 779 780
    class PipelineSchedule < Grape::Entity
      expose :id
      expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active
781
      expose :created_at, :updated_at
782 783 784
      expose :owner, using: Entities::UserBasic
    end

Shinya Maeda's avatar
Shinya Maeda committed
785 786 787 788
    class PipelineScheduleDetails < PipelineSchedule
      expose :last_pipeline, using: Entities::PipelineBasic
    end

789
    class EnvironmentBasic < Grape::Entity
Nick Thomas's avatar
Nick Thomas committed
790
      expose :id, :name, :slug, :external_url
791 792
    end

793
    class Environment < EnvironmentBasic
794
      expose :project, using: Entities::BasicProjectDetails
Z.J. van de Weg's avatar
Z.J. van de Weg committed
795 796 797 798
    end

    class Deployment < Grape::Entity
      expose :id, :iid, :ref, :sha, :created_at
799 800
      expose :user,        using: Entities::UserBasic
      expose :environment, using: Entities::EnvironmentBasic
801
      expose :deployable,  using: Entities::Job
802 803
    end

804
    class RepoLicense < Grape::Entity
805 806
      expose :key, :name, :nickname
      expose :featured, as: :popular
807 808 809
      expose :url, as: :html_url
      expose(:source_url) { |license| license.meta['source'] }
      expose(:description) { |license| license.meta['description'] }
810 811 812
      expose(:conditions) { |license| license.meta['conditions'] }
      expose(:permissions) { |license| license.meta['permissions'] }
      expose(:limitations) { |license| license.meta['limitations'] }
813 814
      expose :content
    end
815

816
    class TemplatesList < Grape::Entity
817 818 819
      expose :name
    end

820
    class Template < Grape::Entity
821 822
      expose :name, :content
    end
823 824 825 826 827

    class BroadcastMessage < Grape::Entity
      expose :id, :message, :starts_at, :ends_at, :color, :font
      expose :active?, as: :active
    end
Tomasz Maczukin's avatar
Tomasz Maczukin committed
828

829
    class PersonalAccessToken < Grape::Entity
830 831 832 833 834 835 836
      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

837
    class PersonalAccessTokenWithToken < PersonalAccessToken
838 839
      expose :token
    end
840 841 842 843

    class ImpersonationToken < PersonalAccessTokenWithToken
      expose :impersonation
    end
844

845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
    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

867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882
    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
Tomasz Maczukin's avatar
Tomasz Maczukin committed
883

884 885 886
      class RunnerInfo < Grape::Entity
        expose :timeout
      end
Tomasz Maczukin's avatar
Tomasz Maczukin committed
887

888
      class Step < Grape::Entity
Tomasz Maczukin's avatar
Tomasz Maczukin committed
889
        expose :name, :script, :timeout, :when, :allow_failure
890
      end
Tomasz Maczukin's avatar
Tomasz Maczukin committed
891

892
      class Image < Grape::Entity
893 894 895
        expose :name, :entrypoint
      end

896
      class Service < Image
897
        expose :alias, :command
898
      end
Tomasz Maczukin's avatar
Tomasz Maczukin committed
899

900 901
      class Artifacts < Grape::Entity
        expose :name, :untracked, :paths, :when, :expire_in
Tomasz Maczukin's avatar
Tomasz Maczukin committed
902 903
      end

904
      class Cache < Grape::Entity
905
        expose :key, :untracked, :paths, :policy
Tomasz Maczukin's avatar
Tomasz Maczukin committed
906 907
      end

908 909 910
      class Credentials < Grape::Entity
        expose :type, :url, :username, :password
      end
Tomasz Maczukin's avatar
Tomasz Maczukin committed
911

912 913 914 915 916
      class ArtifactFile < Grape::Entity
        expose :filename, :size
      end

      class Dependency < Grape::Entity
917
        expose :id, :name, :token
918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
        expose :artifacts_file, using: ArtifactFile, if: ->(job, _) { job.artifacts? }
      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
941
        expose :services, using: Service
942 943 944
        expose :artifacts, using: Artifacts
        expose :cache, using: Cache
        expose :credentials, using: Credentials
945
        expose :dependencies, using: Dependency
946
      end
Tomasz Maczukin's avatar
Tomasz Maczukin committed
947
    end
948 949 950 951

    class UserAgentDetail < Grape::Entity
      expose :user_agent
      expose :ip_address
952
      expose :submitted, as: :akismet_submitted
953
    end
954 955 956 957 958 959

    class RepositoryStorageHealth < Grape::Entity
      expose :storage_name
      expose :failing_on_hosts
      expose :total_failures
    end
Nihad Abbasov's avatar
Nihad Abbasov committed
960 961
  end
end