/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

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