PageRenderTime 82ms CodeModel.GetById 1ms app.highlight 76ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/api/entities.rb

https://gitlab.com/vicvega/gitlab-ce
Ruby | 640 lines | 534 code | 102 blank | 4 comment | 17 complexity | 2689c897b8314fb50f2c1c151d5ba3af MD5 | raw file
  1module API
  2  module Entities
  3    class UserSafe < Grape::Entity
  4      expose :name, :username
  5    end
  6
  7    class UserBasic < UserSafe
  8      expose :id, :state, :avatar_url
  9
 10      expose :web_url do |user, options|
 11        Gitlab::Routing.url_helpers.user_url(user)
 12      end
 13    end
 14
 15    class User < UserBasic
 16      expose :created_at
 17      expose :is_admin?, as: :is_admin
 18      expose :bio, :location, :skype, :linkedin, :twitter, :website_url, :organization
 19    end
 20
 21    class Identity < Grape::Entity
 22      expose :provider, :extern_uid
 23    end
 24
 25    class UserFull < User
 26      expose :last_sign_in_at
 27      expose :confirmed_at
 28      expose :email
 29      expose :theme_id, :color_scheme_id, :projects_limit, :current_sign_in_at
 30      expose :identities, using: Entities::Identity
 31      expose :can_create_group?, as: :can_create_group
 32      expose :can_create_project?, as: :can_create_project
 33      expose :two_factor_enabled?, as: :two_factor_enabled
 34      expose :external
 35    end
 36
 37    class UserLogin < UserFull
 38      expose :private_token
 39    end
 40
 41    class Email < Grape::Entity
 42      expose :id, :email
 43    end
 44
 45    class Hook < Grape::Entity
 46      expose :id, :url, :created_at, :push_events, :tag_push_events
 47      expose :enable_ssl_verification
 48    end
 49
 50    class ProjectHook < Hook
 51      expose :project_id, :issues_events, :merge_requests_events
 52      expose :note_events, :build_events, :pipeline_events, :wiki_page_events
 53    end
 54
 55    class BasicProjectDetails < Grape::Entity
 56      expose :id
 57      expose :http_url_to_repo, :web_url
 58      expose :name, :name_with_namespace
 59      expose :path, :path_with_namespace
 60    end
 61
 62    class SharedGroup < Grape::Entity
 63      expose :group_id
 64      expose :group_name do |group_link, options|
 65        group_link.group.name
 66      end
 67      expose :group_access, as: :group_access_level
 68    end
 69
 70    class Project < Grape::Entity
 71      expose :id, :description, :default_branch, :tag_list
 72      expose :public?, as: :public
 73      expose :archived?, as: :archived
 74      expose :visibility_level, :ssh_url_to_repo, :http_url_to_repo, :web_url
 75      expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
 76      expose :name, :name_with_namespace
 77      expose :path, :path_with_namespace
 78      expose :container_registry_enabled
 79
 80      # Expose old field names with the new permissions methods to keep API compatible
 81      expose(:issues_enabled) { |project, options| project.feature_available?(:issues, options[:user]) }
 82      expose(:merge_requests_enabled) { |project, options| project.feature_available?(:merge_requests, options[:user]) }
 83      expose(:wiki_enabled) { |project, options| project.feature_available?(:wiki, options[:user]) }
 84      expose(:builds_enabled) { |project, options| project.feature_available?(:builds, options[:user]) }
 85      expose(:snippets_enabled) { |project, options| project.feature_available?(:snippets, options[:user]) }
 86
 87      expose :created_at, :last_activity_at
 88      expose :shared_runners_enabled
 89      expose :lfs_enabled?, as: :lfs_enabled
 90      expose :creator_id
 91      expose :namespace
 92      expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda{ |project, options| project.forked? }
 93      expose :avatar_url
 94      expose :star_count, :forks_count
 95      expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:user]) && project.default_issues_tracker? }
 96      expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
 97      expose :public_builds
 98      expose :shared_with_groups do |project, options|
 99        SharedGroup.represent(project.project_group_links.all, options)
100      end
101      expose :only_allow_merge_if_build_succeeds
102      expose :request_access_enabled
103      expose :only_allow_merge_if_all_discussions_are_resolved
104    end
105
106    class Member < UserBasic
107      expose :access_level do |user, options|
108        member = options[:member] || options[:source].members.find_by(user_id: user.id)
109        member.access_level
110      end
111      expose :expires_at do |user, options|
112        member = options[:member] || options[:source].members.find_by(user_id: user.id)
113        member.expires_at
114      end
115    end
116
117    class AccessRequester < UserBasic
118      expose :requested_at do |user, options|
119        access_requester = options[:access_requester] || options[:source].requesters.find_by(user_id: user.id)
120        access_requester.requested_at
121      end
122    end
123
124    class Group < Grape::Entity
125      expose :id, :name, :path, :description, :visibility_level
126      expose :lfs_enabled?, as: :lfs_enabled
127      expose :avatar_url
128      expose :web_url
129      expose :request_access_enabled
130    end
131
132    class GroupDetail < Group
133      expose :projects, using: Entities::Project
134      expose :shared_projects, using: Entities::Project
135    end
136
137    class RepoBranch < Grape::Entity
138      expose :name
139
140      expose :commit do |repo_branch, options|
141        options[:project].repository.commit(repo_branch.dereferenced_target)
142      end
143
144      expose :protected do |repo_branch, options|
145        options[:project].protected_branch? repo_branch.name
146      end
147
148      expose :developers_can_push do |repo_branch, options|
149        project = options[:project]
150        access_levels = project.protected_branches.matching(repo_branch.name).map(&:push_access_levels).flatten
151        access_levels.any? { |access_level| access_level.access_level == Gitlab::Access::DEVELOPER }
152      end
153
154      expose :developers_can_merge do |repo_branch, options|
155        project = options[:project]
156        access_levels = project.protected_branches.matching(repo_branch.name).map(&:merge_access_levels).flatten
157        access_levels.any? { |access_level| access_level.access_level == Gitlab::Access::DEVELOPER }
158      end
159    end
160
161    class RepoTreeObject < Grape::Entity
162      expose :id, :name, :type
163
164      expose :mode do |obj, options|
165        filemode = obj.mode.to_s(8)
166        filemode = "0" + filemode if filemode.length < 6
167        filemode
168      end
169    end
170
171    class RepoCommit < Grape::Entity
172      expose :id, :short_id, :title, :author_name, :author_email, :created_at
173      expose :safe_message, as: :message
174    end
175
176    class RepoCommitStats < Grape::Entity
177      expose :additions, :deletions, :total
178    end
179
180    class RepoCommitDetail < RepoCommit
181      expose :parent_ids, :committed_date, :authored_date
182      expose :stats, using: Entities::RepoCommitStats
183      expose :status
184    end
185
186    class ProjectSnippet < Grape::Entity
187      expose :id, :title, :file_name
188      expose :author, using: Entities::UserBasic
189      expose :updated_at, :created_at
190
191      # TODO (rspeicher): Deprecated; remove in 9.0
192      expose(:expires_at) { |snippet| nil }
193
194      expose :web_url do |snippet, options|
195        Gitlab::UrlBuilder.build(snippet)
196      end
197    end
198
199    class ProjectEntity < Grape::Entity
200      expose :id, :iid
201      expose(:project_id) { |entity| entity.project.id }
202      expose :title, :description
203      expose :state, :created_at, :updated_at
204    end
205
206    class RepoDiff < Grape::Entity
207      expose :old_path, :new_path, :a_mode, :b_mode, :diff
208      expose :new_file, :renamed_file, :deleted_file
209    end
210
211    class Milestone < ProjectEntity
212      expose :due_date
213    end
214
215    class Issue < ProjectEntity
216      expose :label_names, as: :labels
217      expose :milestone, using: Entities::Milestone
218      expose :assignee, :author, using: Entities::UserBasic
219
220      expose :subscribed do |issue, options|
221        issue.subscribed?(options[:current_user])
222      end
223      expose :user_notes_count
224      expose :upvotes, :downvotes
225      expose :due_date
226      expose :confidential
227
228      expose :web_url do |issue, options|
229        Gitlab::UrlBuilder.build(issue)
230      end
231    end
232
233    class ExternalIssue < Grape::Entity
234      expose :title
235      expose :id
236    end
237
238    class MergeRequest < ProjectEntity
239      expose :target_branch, :source_branch
240      expose :upvotes, :downvotes
241      expose :author, :assignee, using: Entities::UserBasic
242      expose :source_project_id, :target_project_id
243      expose :label_names, as: :labels
244      expose :work_in_progress?, as: :work_in_progress
245      expose :milestone, using: Entities::Milestone
246      expose :merge_when_build_succeeds
247      expose :merge_status
248      expose :diff_head_sha, as: :sha
249      expose :merge_commit_sha
250      expose :subscribed do |merge_request, options|
251        merge_request.subscribed?(options[:current_user])
252      end
253      expose :user_notes_count
254      expose :should_remove_source_branch?, as: :should_remove_source_branch
255      expose :force_remove_source_branch?, as: :force_remove_source_branch
256
257      expose :web_url do |merge_request, options|
258        Gitlab::UrlBuilder.build(merge_request)
259      end
260    end
261
262    class MergeRequestChanges < MergeRequest
263      expose :diffs, as: :changes, using: Entities::RepoDiff do |compare, _|
264        compare.raw_diffs(all_diffs: true).to_a
265      end
266    end
267
268    class MergeRequestDiff < Grape::Entity
269      expose :id, :head_commit_sha, :base_commit_sha, :start_commit_sha,
270        :created_at, :merge_request_id, :state, :real_size
271    end
272
273    class MergeRequestDiffFull < MergeRequestDiff
274      expose :commits, using: Entities::RepoCommit
275
276      expose :diffs, using: Entities::RepoDiff do |compare, _|
277        compare.raw_diffs(all_diffs: true).to_a
278      end
279    end
280
281    class SSHKey < Grape::Entity
282      expose :id, :title, :key, :created_at
283    end
284
285    class SSHKeyWithUser < SSHKey
286      expose :user, using: Entities::UserFull
287    end
288
289    class Note < Grape::Entity
290      expose :id
291      expose :note, as: :body
292      expose :attachment_identifier, as: :attachment
293      expose :author, using: Entities::UserBasic
294      expose :created_at, :updated_at
295      expose :system?, as: :system
296      expose :noteable_id, :noteable_type
297      # upvote? and downvote? are deprecated, always return false
298      expose(:upvote?)    { |note| false }
299      expose(:downvote?)  { |note| false }
300    end
301
302    class AwardEmoji < Grape::Entity
303      expose :id
304      expose :name
305      expose :user, using: Entities::UserBasic
306      expose :created_at, :updated_at
307      expose :awardable_id, :awardable_type
308    end
309
310    class MRNote < Grape::Entity
311      expose :note
312      expose :author, using: Entities::UserBasic
313    end
314
315    class CommitNote < Grape::Entity
316      expose :note
317      expose(:path) { |note| note.diff_file.try(:file_path) if note.diff_note? }
318      expose(:line) { |note| note.diff_line.try(:new_line) if note.diff_note? }
319      expose(:line_type) { |note| note.diff_line.try(:type) if note.diff_note? }
320      expose :author, using: Entities::UserBasic
321      expose :created_at
322    end
323
324    class CommitStatus < Grape::Entity
325      expose :id, :sha, :ref, :status, :name, :target_url, :description,
326             :created_at, :started_at, :finished_at, :allow_failure
327      expose :author, using: Entities::UserBasic
328    end
329
330    class Event < Grape::Entity
331      expose :title, :project_id, :action_name
332      expose :target_id, :target_type, :author_id
333      expose :data, :target_title
334      expose :created_at
335      expose :note, using: Entities::Note, if: ->(event, options) { event.note? }
336      expose :author, using: Entities::UserBasic, if: ->(event, options) { event.author }
337
338      expose :author_username do |event, options|
339        if event.author
340          event.author.username
341        end
342      end
343    end
344
345    class ProjectGroupLink < Grape::Entity
346      expose :id, :project_id, :group_id, :group_access, :expires_at
347    end
348
349    class Todo < Grape::Entity
350      expose :id
351      expose :project, using: Entities::BasicProjectDetails
352      expose :author, using: Entities::UserBasic
353      expose :action_name
354      expose :target_type
355
356      expose :target do |todo, options|
357        Entities.const_get(todo.target_type).represent(todo.target, options)
358      end
359
360      expose :target_url do |todo, options|
361        target_type   = todo.target_type.underscore
362        target_url    = "namespace_project_#{target_type}_url"
363        target_anchor = "note_#{todo.note_id}" if todo.note_id?
364
365        Gitlab::Application.routes.url_helpers.public_send(target_url,
366          todo.project.namespace, todo.project, todo.target, anchor: target_anchor)
367      end
368
369      expose :body
370      expose :state
371      expose :created_at
372    end
373
374    class Namespace < Grape::Entity
375      expose :id, :path, :kind
376    end
377
378    class MemberAccess < Grape::Entity
379      expose :access_level
380      expose :notification_level do |member, options|
381        if member.notification_setting
382          ::NotificationSetting.levels[member.notification_setting.level]
383        end
384      end
385    end
386
387    class ProjectAccess < MemberAccess
388    end
389
390    class GroupAccess < MemberAccess
391    end
392
393    class NotificationSetting < Grape::Entity
394      expose :level
395      expose :events, if: ->(notification_setting, _) { notification_setting.custom? } do
396        ::NotificationSetting::EMAIL_EVENTS.each do |event|
397          expose event
398        end
399      end
400    end
401
402    class GlobalNotificationSetting < NotificationSetting
403      expose :notification_email do |notification_setting, options|
404        notification_setting.user.notification_email
405      end
406    end
407
408    class ProjectService < Grape::Entity
409      expose :id, :title, :created_at, :updated_at, :active
410      expose :push_events, :issues_events, :merge_requests_events
411      expose :tag_push_events, :note_events, :build_events, :pipeline_events
412      # Expose serialized properties
413      expose :properties do |service, options|
414        field_names = service.fields.
415          select { |field| options[:include_passwords] || field[:type] != 'password' }.
416          map { |field| field[:name] }
417        service.properties.slice(*field_names)
418      end
419    end
420
421    class ProjectWithAccess < Project
422      expose :permissions do
423        expose :project_access, using: Entities::ProjectAccess do |project, options|
424          project.project_members.find_by(user_id: options[:user].id)
425        end
426
427        expose :group_access, using: Entities::GroupAccess do |project, options|
428          if project.group
429            project.group.group_members.find_by(user_id: options[:user].id)
430          end
431        end
432      end
433    end
434
435    class LabelBasic < Grape::Entity
436      expose :id, :name, :color, :description
437    end
438
439    class Label < LabelBasic
440      expose :open_issues_count, :closed_issues_count, :open_merge_requests_count
441      expose :priority do |label, options|
442        label.priority(options[:project])
443      end
444
445      expose :subscribed do |label, options|
446        label.subscribed?(options[:current_user])
447      end
448    end
449
450    class List < Grape::Entity
451      expose :id
452      expose :label, using: Entities::LabelBasic
453      expose :position
454    end
455
456    class Board < Grape::Entity
457      expose :id
458      expose :lists, using: Entities::List do |board|
459        board.lists.destroyable
460      end
461    end
462
463    class Compare < Grape::Entity
464      expose :commit, using: Entities::RepoCommit do |compare, options|
465        Commit.decorate(compare.commits, nil).last
466      end
467
468      expose :commits, using: Entities::RepoCommit do |compare, options|
469        Commit.decorate(compare.commits, nil)
470      end
471
472      expose :diffs, using: Entities::RepoDiff do |compare, options|
473        compare.diffs(all_diffs: true).to_a
474      end
475
476      expose :compare_timeout do |compare, options|
477        compare.diffs.overflow?
478      end
479
480      expose :same, as: :compare_same_ref
481    end
482
483    class Contributor < Grape::Entity
484      expose :name, :email, :commits, :additions, :deletions
485    end
486
487    class BroadcastMessage < Grape::Entity
488      expose :message, :starts_at, :ends_at, :color, :font
489    end
490
491    class ApplicationSetting < Grape::Entity
492      expose :id
493      expose :default_projects_limit
494      expose :signup_enabled
495      expose :signin_enabled
496      expose :gravatar_enabled
497      expose :sign_in_text
498      expose :after_sign_up_text
499      expose :created_at
500      expose :updated_at
501      expose :home_page_url
502      expose :default_branch_protection
503      expose :restricted_visibility_levels
504      expose :max_attachment_size
505      expose :session_expire_delay
506      expose :default_project_visibility
507      expose :default_snippet_visibility
508      expose :default_group_visibility
509      expose :domain_whitelist
510      expose :domain_blacklist_enabled
511      expose :domain_blacklist
512      expose :user_oauth_applications
513      expose :after_sign_out_path
514      expose :container_registry_token_expire_delay
515      expose :repository_storage
516      expose :repository_storages
517      expose :koding_enabled
518      expose :koding_url
519    end
520
521    class Release < Grape::Entity
522      expose :tag, as: :tag_name
523      expose :description
524    end
525
526    class RepoTag < Grape::Entity
527      expose :name, :message
528
529      expose :commit do |repo_tag, options|
530        options[:project].repository.commit(repo_tag.dereferenced_target)
531      end
532
533      expose :release, using: Entities::Release do |repo_tag, options|
534        options[:project].releases.find_by(tag: repo_tag.name)
535      end
536    end
537
538    class TriggerRequest < Grape::Entity
539      expose :id, :variables
540    end
541
542    class Runner < Grape::Entity
543      expose :id
544      expose :description
545      expose :active
546      expose :is_shared
547      expose :name
548    end
549
550    class RunnerDetails < Runner
551      expose :tag_list
552      expose :run_untagged
553      expose :locked
554      expose :version, :revision, :platform, :architecture
555      expose :contacted_at
556      expose :token, if: lambda { |runner, options| options[:current_user].is_admin? || !runner.is_shared? }
557      expose :projects, with: Entities::BasicProjectDetails do |runner, options|
558        if options[:current_user].is_admin?
559          runner.projects
560        else
561          options[:current_user].authorized_projects.where(id: runner.projects)
562        end
563      end
564    end
565
566    class BuildArtifactFile < Grape::Entity
567      expose :filename, :size
568    end
569
570    class PipelineBasic < Grape::Entity
571      expose :id, :sha, :ref, :status
572    end
573
574    class Build < Grape::Entity
575      expose :id, :status, :stage, :name, :ref, :tag, :coverage
576      expose :created_at, :started_at, :finished_at
577      expose :user, with: User
578      expose :artifacts_file, using: BuildArtifactFile, if: -> (build, opts) { build.artifacts? }
579      expose :commit, with: RepoCommit
580      expose :runner, with: Runner
581      expose :pipeline, with: PipelineBasic
582    end
583
584    class Trigger < Grape::Entity
585      expose :token, :created_at, :updated_at, :deleted_at, :last_used
586    end
587
588    class Variable < Grape::Entity
589      expose :key, :value
590    end
591
592    class Pipeline < PipelineBasic
593      expose :before_sha, :tag, :yaml_errors
594
595      expose :user, with: Entities::UserBasic
596      expose :created_at, :updated_at, :started_at, :finished_at, :committed_at
597      expose :duration
598    end
599
600    class EnvironmentBasic < Grape::Entity
601      expose :id, :name, :external_url
602    end
603
604    class Environment < EnvironmentBasic
605      expose :project, using: Entities::Project
606    end
607
608    class Deployment < Grape::Entity
609      expose :id, :iid, :ref, :sha, :created_at
610      expose :user,        using: Entities::UserBasic
611      expose :environment, using: Entities::EnvironmentBasic
612      expose :deployable,  using: Entities::Build
613    end
614
615    class RepoLicense < Grape::Entity
616      expose :key, :name, :nickname
617      expose :featured, as: :popular
618      expose :url, as: :html_url
619      expose(:source_url) { |license| license.meta['source'] }
620      expose(:description) { |license| license.meta['description'] }
621      expose(:conditions) { |license| license.meta['conditions'] }
622      expose(:permissions) { |license| license.meta['permissions'] }
623      expose(:limitations) { |license| license.meta['limitations'] }
624      expose :content
625    end
626
627    class TemplatesList < Grape::Entity
628      expose :name
629    end
630
631    class Template < Grape::Entity
632      expose :name, :content
633    end
634
635    class BroadcastMessage < Grape::Entity
636      expose :id, :message, :starts_at, :ends_at, :color, :font
637      expose :active?, as: :active
638    end
639  end
640end