gitlab-org--gitlab-foss/lib/api/entities.rb

979 lines
30 KiB
Ruby
Raw Normal View History

module API
2012-06-27 07:32:56 -04:00
module Entities
class UserSafe < Grape::Entity
expose :name, :username
end
class UserBasic < UserSafe
expose :id, :state
expose :avatar_url do |user, options|
user.avatar_url(only_path: false)
end
2015-07-30 05:56:15 -04:00
expose :web_url do |user, options|
Gitlab::Routing.url_helpers.user_url(user)
2015-07-30 05:56:15 -04:00
end
2012-06-27 07:32:56 -04:00
end
2012-06-27 08:51:39 -04:00
class User < UserBasic
expose :created_at
expose :bio, :location, :skype, :linkedin, :twitter, :website_url, :organization
end
class UserActivity < Grape::Entity
expose :username
expose :last_activity_on
expose :last_activity_on, as: :last_activity_at # Back-compat
end
class Identity < Grape::Entity
expose :provider, :extern_uid
end
class UserPublic < User
expose :last_sign_in_at
expose :confirmed_at
expose :last_activity_on
expose :email
expose :color_scheme_id, :projects_limit, :current_sign_in_at
expose :identities, using: Entities::Identity
expose :can_create_group?, as: :can_create_group
expose :can_create_project?, as: :can_create_project
expose :two_factor_enabled?, as: :two_factor_enabled
2016-03-14 19:11:20 -04:00
expose :external
end
class UserWithAdmin < UserPublic
expose :admin?, as: :is_admin
end
class UserWithPrivateDetails < UserWithAdmin
expose :private_token
end
class Email < Grape::Entity
expose :id, :email
end
2012-09-08 13:51:12 -04:00
class Hook < Grape::Entity
expose :id, :url, :created_at, :push_events, :tag_push_events, :repository_update_events
2016-10-19 10:08:30 -04:00
expose :enable_ssl_verification
2012-09-08 13:51:12 -04:00
end
class ProjectHook < Hook
expose :project_id, :issues_events, :merge_requests_events
expose :note_events, :pipeline_events, :wiki_page_events
expose :job_events
end
2016-07-08 03:34:36 -04:00
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
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
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
expose :archived?, as: :archived
expose :visibility
expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
2016-08-01 18:31:21 -04:00
expose :container_registry_enabled
# Expose old field names with the new permissions methods to keep API compatible
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]) }
expose(:jobs_enabled) { |project, options| project.feature_available?(:builds, options[:current_user]) }
expose(:snippets_enabled) { |project, options| project.feature_available?(:snippets, options[:current_user]) }
2016-08-01 18:31:21 -04:00
expose :shared_runners_enabled
expose :lfs_enabled?, as: :lfs_enabled
expose :creator_id
expose :namespace, using: 'API::Entities::Namespace'
expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda { |project, options| project.forked? }
2017-06-01 10:57:41 -04:00
expose :import_status
expose :import_error, if: lambda { |_project, options| options[:user_can_admin_project] }
expose :avatar_url do |user, options|
user.avatar_url(only_path: false)
end
expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:current_user]) }
2016-01-11 09:27:20 -05:00
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
expose :public_builds, as: :public_jobs
expose :ci_config_path
2016-07-08 03:34:36 -04:00
expose :shared_with_groups do |project, options|
SharedGroup.represent(project.project_group_links.all, options)
end
expose :only_allow_merge_if_pipeline_succeeds
expose :request_access_enabled
expose :only_allow_merge_if_all_discussions_are_resolved
expose :printing_merge_request_link_enabled
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
expose :build_artifacts_size, as: :job_artifacts_size
2012-06-27 08:51:39 -04:00
end
class Member < UserBasic
expose :access_level do |user, options|
member = options[:member] || options[:source].members.find_by(user_id: user.id)
member.access_level
end
expose :expires_at do |user, options|
member = options[:member] || options[:source].members.find_by(user_id: user.id)
member.expires_at
end
end
class AccessRequester < UserBasic
expose :requested_at do |user, options|
access_requester = options[:access_requester] || options[:source].requesters.find_by(user_id: user.id)
access_requester.requested_at
2012-09-21 06:23:17 -04:00
end
2012-09-06 16:49:29 -04:00
end
class Group < Grape::Entity
expose :id, :name, :path, :description, :visibility
expose :lfs_enabled?, as: :lfs_enabled
expose :avatar_url do |user, options|
user.avatar_url(only_path: false)
end
expose :web_url
expose :request_access_enabled
expose :full_name, :full_path
if ::Group.supports_nested_groups?
expose :parent_id
end
expose :statistics, if: :statistics do
with_options format_with: -> (value) { value.to_i } do
expose :storage_size
expose :repository_size
expose :lfs_objects_size
expose :build_artifacts_size, as: :job_artifacts_size
end
end
end
2013-02-18 04:10:58 -05:00
class GroupDetail < Group
expose :projects, using: Entities::Project
2016-07-08 04:59:52 -04:00
expose :shared_projects, using: Entities::Project
end
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
class RepoBranch < Grape::Entity
expose :name
expose :commit, using: Entities::RepoCommit do |repo_branch, options|
options[:project].repository.commit(repo_branch.dereferenced_target)
end
2016-11-28 13:16:15 -05:00
expose :merged do |repo_branch, options|
options[:project].repository.merged_to_root_ref?(repo_branch.name)
end
expose :protected do |repo_branch, options|
2017-08-02 06:16:17 -04:00
::ProtectedBranch.protected?(options[:project], repo_branch.name)
end
expose :developers_can_push do |repo_branch, options|
options[:project].protected_branches.developers_can?(:push, repo_branch.name)
end
expose :developers_can_merge do |repo_branch, options|
options[:project].protected_branches.developers_can?(:merge, repo_branch.name)
end
2012-06-27 08:51:39 -04:00
end
2012-06-29 09:34:08 -04:00
class RepoTreeObject < Grape::Entity
expose :id, :name, :type, :path
expose :mode do |obj, options|
2017-04-01 11:55:14 -04:00
filemode = obj.mode
filemode = "0" + filemode if filemode.length < 6
filemode
end
end
2012-06-29 09:34:08 -04:00
class ProjectSnippet < Grape::Entity
2017-05-03 11:26:49 -04:00
expose :id, :title, :file_name, :description
expose :author, using: Entities::UserBasic
expose :updated_at, :created_at
expose :web_url do |snippet, options|
Gitlab::UrlBuilder.build(snippet)
end
2012-06-29 09:34:08 -04:00
end
2012-07-24 08:19:51 -04:00
class PersonalSnippet < Grape::Entity
2017-05-03 11:26:49 -04:00
expose :id, :title, :file_name, :description
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
class ProjectEntity < Grape::Entity
expose :id, :iid
2017-07-07 11:08:49 -04:00
expose(:project_id) { |entity| entity&.project.try(:id) }
expose :title, :description
expose :state, :created_at, :updated_at
end
class RepoDiff < Grape::Entity
expose :old_path, :new_path, :a_mode, :b_mode, :diff
expose :new_file?, as: :new_file
expose :renamed_file?, as: :renamed_file
expose :deleted_file?, as: :deleted_file
end
2017-08-02 06:16:17 -04:00
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
2017-07-07 11:08:49 -04:00
class Milestone < Grape::Entity
expose :id, :iid
2017-07-12 15:58:48 -04:00
expose :project_id, if: -> (entity, options) { entity&.project_id }
expose :group_id, if: -> (entity, options) { entity&.group_id }
2017-07-07 11:08:49 -04:00
expose :title, :description
expose :state, :created_at, :updated_at
expose :due_date
2016-11-15 12:48:30 -05:00
expose :start_date
2012-07-24 08:19:51 -04:00
end
class IssueBasic < ProjectEntity
expose :label_names, as: :labels
expose :milestone, using: Entities::Milestone
expose :assignees, :author, using: Entities::UserBasic
expose :assignee, using: ::API::Entities::UserBasic do |issue, options|
issue.assignees.first
end
2016-04-08 02:41:10 -04:00
2016-06-01 05:23:09 -04:00
expose :user_notes_count
2016-05-11 16:43:58 -04:00
expose :upvotes, :downvotes
2016-07-12 11:59:21 -04:00
expose :due_date
2016-07-15 10:21:53 -04:00
expose :confidential
expose :web_url do |issue, options|
Gitlab::UrlBuilder.build(issue)
end
2012-07-24 08:19:51 -04:00
end
2012-09-16 10:52:06 -04:00
class Issue < IssueBasic
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
expose :subscribed do |issue, options|
issue.subscribed?(options[:current_user], options[:project] || issue.project)
end
end
class IssuableTimeStats < Grape::Entity
expose :time_estimate
expose :total_time_spent
expose :human_time_estimate
expose :human_total_time_spent
end
class ExternalIssue < Grape::Entity
expose :title
expose :id
end
class MergeRequestSimple < ProjectEntity
expose :title
expose :web_url do |merge_request, options|
Gitlab::UrlBuilder.build(merge_request)
end
end
class MergeRequestBasic < ProjectEntity
2015-11-11 08:12:51 -05:00
expose :target_branch, :source_branch
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
expose :author, :assignee, using: Entities::UserBasic
expose :source_project_id, :target_project_id
expose :labels do |merge_request, options|
# Avoids an N+1 query since labels are preloaded
merge_request.labels.map(&:title).sort
end
2015-07-09 13:21:37 -04:00
expose :work_in_progress?, as: :work_in_progress
expose :milestone, using: Entities::Milestone
expose :merge_when_pipeline_succeeds
expose :merge_status
expose :diff_head_sha, as: :sha
expose :merge_commit_sha
2016-06-01 05:23:09 -04:00
expose :user_notes_count
expose :should_remove_source_branch?, as: :should_remove_source_branch
expose :force_remove_source_branch?, as: :force_remove_source_branch
expose :web_url do |merge_request, options|
Gitlab::UrlBuilder.build(merge_request)
end
2012-09-16 10:52:06 -04:00
end
2012-10-21 07:00:27 -04:00
class MergeRequest < MergeRequestBasic
expose :subscribed do |merge_request, options|
merge_request.subscribed?(options[:current_user], options[:project])
end
end
class MergeRequestChanges < MergeRequest
expose :diffs, as: :changes, using: Entities::RepoDiff do |compare, _|
2017-05-31 15:41:25 -04:00
compare.raw_diffs(limits: false).to_a
end
end
class MergeRequestDiff < Grape::Entity
expose :id, :head_commit_sha, :base_commit_sha, :start_commit_sha,
:created_at, :merge_request_id, :state, :real_size
end
class MergeRequestDiffFull < MergeRequestDiff
expose :commits, using: Entities::RepoCommit
expose :diffs, using: Entities::RepoDiff do |compare, _|
2017-05-31 15:41:25 -04:00
compare.raw_diffs(limits: false).to_a
end
end
class SSHKey < Grape::Entity
expose :id, :title, :key, :created_at, :can_push
2012-10-21 07:00:27 -04:00
end
2012-10-21 12:48:56 -04:00
class SSHKeyWithUser < SSHKey
expose :user, using: Entities::UserPublic
end
2012-10-21 12:48:56 -04:00
class Note < Grape::Entity
2017-08-08 07:31:55 -04:00
# Only Issue and MergeRequest have iid
NOTEABLE_TYPES_WITH_IID = %w(Issue MergeRequest).freeze
expose :id
expose :note, as: :body
2013-03-19 07:28:29 -04:00
expose :attachment_identifier, as: :attachment
2012-10-21 12:48:56 -04:00
expose :author, using: Entities::UserBasic
2016-04-12 06:32:34 -04:00
expose :created_at, :updated_at
expose :system?, as: :system
expose :noteable_id, :noteable_type
2017-08-08 07:31:55 -04:00
# Avoid N+1 queries as much as possible
expose(:noteable_iid) { |note| note.noteable.iid if NOTEABLE_TYPES_WITH_IID.include?(note.noteable_type) }
2012-10-21 12:48:56 -04:00
end
class AwardEmoji < Grape::Entity
expose :id
expose :name
expose :user, using: Entities::UserBasic
expose :created_at, :updated_at
expose :awardable_id, :awardable_type
end
class MRNote < Grape::Entity
expose :note
expose :author, using: Entities::UserBasic
end
2013-06-06 12:19:17 -04:00
2014-06-27 10:48:30 -04:00
class CommitNote < Grape::Entity
expose :note
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? }
2014-06-27 10:48:30 -04:00
expose :author, using: Entities::UserBasic
expose :created_at
2014-06-27 10:48:30 -04:00
end
2015-10-06 06:01:16 -04:00
class CommitStatus < Grape::Entity
expose :id, :sha, :ref, :status, :name, :target_url, :description,
:created_at, :started_at, :finished_at, :allow_failure, :coverage
2015-10-12 06:15:48 -04:00
expose :author, using: Entities::UserBasic
2015-10-06 06:01:16 -04:00
end
Migrate events into a new format This commit migrates events data in such a way that push events are stored much more efficiently. This is done by creating a shadow table called "events_for_migration", and a table called "push_event_payloads" which is used for storing push data of push events. The background migration in this commit will copy events from the "events" table into the "events_for_migration" table, push events in will also have a row created in "push_event_payloads". This approach allows us to reclaim space in the next release by simply swapping the "events" and "events_for_migration" tables, then dropping the old events (now "events_for_migration") table. The new table structure is also optimised for storage space, and does not include the unused "title" column nor the "data" column (since this data is moved to "push_event_payloads"). == Newly Created Events Newly created events are inserted into both "events" and "events_for_migration", both using the exact same primary key value. The table "push_event_payloads" in turn has a foreign key to the _shadow_ table. This removes the need for recreating and validating the foreign key after swapping the tables. Since the shadow table also has a foreign key to "projects.id" we also don't have to worry about orphaned rows. This approach however does require some additional storage as we're duplicating a portion of the events data for at least 1 release. The exact amount is hard to estimate, but for GitLab.com this is expected to be between 10 and 20 GB at most. The background migration in this commit deliberately does _not_ update the "events" table as doing so would put a lot of pressure on PostgreSQL's auto vacuuming system. == Supporting Both Old And New Events Application code has also been adjusted to support push events using both the old and new data formats. This is done by creating a PushEvent class which extends the regular Event class. Using Rails' Single Table Inheritance system we can ensure the right class is used for the right data, which in this case is based on the value of `events.action`. To support displaying old and new data at the same time the PushEvent class re-defines a few methods of the Event class, falling back to their original implementations for push events in the old format. Once all existing events have been migrated the various push event related methods can be removed from the Event model, and the calls to `super` can be removed from the methods in the PushEvent model. The UI and event atom feed have also been slightly changed to better handle this new setup, fortunately only a few changes were necessary to make this work. == API Changes The API only displays push data of events in the new format. Supporting both formats in the API is a bit more difficult compared to the UI. Since the old push data was not really well documented (apart from one example that used an incorrect "action" nmae) I decided that supporting both was not worth the effort, especially since events will be migrated in a few days _and_ new events are created in the correct format.
2017-07-10 11:43:57 -04:00
class PushEventPayload < Grape::Entity
expose :commit_count, :action, :ref_type, :commit_from, :commit_to
expose :ref, :commit_title
end
2013-06-06 12:19:17 -04:00
class Event < Grape::Entity
expose :title, :project_id, :action_name
2017-08-02 02:18:17 -04:00
expose :target_id, :target_iid, :target_type, :author_id
Migrate events into a new format This commit migrates events data in such a way that push events are stored much more efficiently. This is done by creating a shadow table called "events_for_migration", and a table called "push_event_payloads" which is used for storing push data of push events. The background migration in this commit will copy events from the "events" table into the "events_for_migration" table, push events in will also have a row created in "push_event_payloads". This approach allows us to reclaim space in the next release by simply swapping the "events" and "events_for_migration" tables, then dropping the old events (now "events_for_migration") table. The new table structure is also optimised for storage space, and does not include the unused "title" column nor the "data" column (since this data is moved to "push_event_payloads"). == Newly Created Events Newly created events are inserted into both "events" and "events_for_migration", both using the exact same primary key value. The table "push_event_payloads" in turn has a foreign key to the _shadow_ table. This removes the need for recreating and validating the foreign key after swapping the tables. Since the shadow table also has a foreign key to "projects.id" we also don't have to worry about orphaned rows. This approach however does require some additional storage as we're duplicating a portion of the events data for at least 1 release. The exact amount is hard to estimate, but for GitLab.com this is expected to be between 10 and 20 GB at most. The background migration in this commit deliberately does _not_ update the "events" table as doing so would put a lot of pressure on PostgreSQL's auto vacuuming system. == Supporting Both Old And New Events Application code has also been adjusted to support push events using both the old and new data formats. This is done by creating a PushEvent class which extends the regular Event class. Using Rails' Single Table Inheritance system we can ensure the right class is used for the right data, which in this case is based on the value of `events.action`. To support displaying old and new data at the same time the PushEvent class re-defines a few methods of the Event class, falling back to their original implementations for push events in the old format. Once all existing events have been migrated the various push event related methods can be removed from the Event model, and the calls to `super` can be removed from the methods in the PushEvent model. The UI and event atom feed have also been slightly changed to better handle this new setup, fortunately only a few changes were necessary to make this work. == API Changes The API only displays push data of events in the new format. Supporting both formats in the API is a bit more difficult compared to the UI. Since the old push data was not really well documented (apart from one example that used an incorrect "action" nmae) I decided that supporting both was not worth the effort, especially since events will be migrated in a few days _and_ new events are created in the correct format.
2017-07-10 11:43:57 -04:00
expose :target_title
expose :created_at
expose :note, using: Entities::Note, if: ->(event, options) { event.note? }
expose :author, using: Entities::UserBasic, if: ->(event, options) { event.author }
Migrate events into a new format This commit migrates events data in such a way that push events are stored much more efficiently. This is done by creating a shadow table called "events_for_migration", and a table called "push_event_payloads" which is used for storing push data of push events. The background migration in this commit will copy events from the "events" table into the "events_for_migration" table, push events in will also have a row created in "push_event_payloads". This approach allows us to reclaim space in the next release by simply swapping the "events" and "events_for_migration" tables, then dropping the old events (now "events_for_migration") table. The new table structure is also optimised for storage space, and does not include the unused "title" column nor the "data" column (since this data is moved to "push_event_payloads"). == Newly Created Events Newly created events are inserted into both "events" and "events_for_migration", both using the exact same primary key value. The table "push_event_payloads" in turn has a foreign key to the _shadow_ table. This removes the need for recreating and validating the foreign key after swapping the tables. Since the shadow table also has a foreign key to "projects.id" we also don't have to worry about orphaned rows. This approach however does require some additional storage as we're duplicating a portion of the events data for at least 1 release. The exact amount is hard to estimate, but for GitLab.com this is expected to be between 10 and 20 GB at most. The background migration in this commit deliberately does _not_ update the "events" table as doing so would put a lot of pressure on PostgreSQL's auto vacuuming system. == Supporting Both Old And New Events Application code has also been adjusted to support push events using both the old and new data formats. This is done by creating a PushEvent class which extends the regular Event class. Using Rails' Single Table Inheritance system we can ensure the right class is used for the right data, which in this case is based on the value of `events.action`. To support displaying old and new data at the same time the PushEvent class re-defines a few methods of the Event class, falling back to their original implementations for push events in the old format. Once all existing events have been migrated the various push event related methods can be removed from the Event model, and the calls to `super` can be removed from the methods in the PushEvent model. The UI and event atom feed have also been slightly changed to better handle this new setup, fortunately only a few changes were necessary to make this work. == API Changes The API only displays push data of events in the new format. Supporting both formats in the API is a bit more difficult compared to the UI. Since the old push data was not really well documented (apart from one example that used an incorrect "action" nmae) I decided that supporting both was not worth the effort, especially since events will be migrated in a few days _and_ new events are created in the correct format.
2017-07-10 11:43:57 -04:00
expose :push_event_payload,
as: :push_data,
using: PushEventPayload,
if: -> (event, _) { event.push? }
expose :author_username do |event, options|
2017-02-07 09:16:46 -05:00
event.author&.username
end
2013-06-06 12:19:17 -04:00
end
class ProjectGroupLink < Grape::Entity
expose :id, :project_id, :group_id, :group_access, :expires_at
end
2016-03-11 14:04:42 -05:00
class Todo < Grape::Entity
expose :id
expose :project, using: Entities::BasicProjectDetails
expose :author, using: Entities::UserBasic
2016-06-15 07:20:30 -04:00
expose :action_name
2016-03-11 14:04:42 -05:00
expose :target_type
expose :target do |todo, options|
target = todo.target_type == 'Commit' ? 'RepoCommit' : todo.target_type
Entities.const_get(target).represent(todo.target, options)
2016-03-11 14:04:42 -05:00
end
expose :target_url do |todo, options|
target_type = todo.target_type.underscore
target_url = "namespace_project_#{target_type}_url"
target_anchor = "note_#{todo.note_id}" if todo.note_id?
2016-03-11 14:04:42 -05:00
Gitlab::Routing
.url_helpers
.public_send(target_url, todo.project.namespace, todo.project, todo.target, anchor: target_anchor) # rubocop:disable GitlabSecurity/PublicSend
2016-03-11 14:04:42 -05:00
end
expose :body
expose :state
expose :created_at
end
class Namespace < Grape::Entity
expose :id, :name, :path, :kind, :full_path, :parent_id
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)
end
end
class MemberAccess < Grape::Entity
expose :access_level
expose :notification_level do |member, options|
if member.notification_setting
::NotificationSetting.levels[member.notification_setting.level]
end
end
end
class ProjectAccess < MemberAccess
end
class GroupAccess < MemberAccess
end
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
class ProjectService < Grape::Entity
expose :id, :title, :created_at, :updated_at, :active
expose :push_events, :issues_events, :merge_requests_events
expose :tag_push_events, :note_events, :pipeline_events
expose :job_events
# Expose serialized properties
expose :properties do |service, options|
2017-06-21 09:48:12 -04:00
field_names = service.fields
.select { |field| options[:include_passwords] || field[:type] != 'password' }
.map { |field| field[:name] }
service.properties.slice(*field_names)
end
end
class ProjectWithAccess < Project
expose :permissions do
expose :project_access, using: Entities::ProjectAccess do |project, options|
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
end
expose :group_access, using: Entities::GroupAccess do |project, options|
if project.group
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
end
end
end
end
class LabelBasic < Grape::Entity
expose :id, :name, :color, :description
end
class Label < LabelBasic
expose :open_issues_count do |label, options|
2016-11-14 10:04:07 -05:00
label.open_issues_count(options[:current_user])
end
2016-11-14 10:04:07 -05:00
expose :closed_issues_count do |label, options|
label.closed_issues_count(options[:current_user])
end
2016-11-14 10:04:07 -05:00
expose :open_merge_requests_count do |label, options|
label.open_merge_requests_count(options[:current_user])
end
expose :priority do |label, options|
label.priority(options[:project])
end
expose :subscribed do |label, options|
label.subscribed?(options[:current_user], options[:project])
end
end
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
class Compare < Grape::Entity
expose :commit, using: Entities::RepoCommit do |compare, options|
Commit.decorate(compare.commits, nil).last
end
expose :commits, using: Entities::RepoCommit do |compare, options|
Commit.decorate(compare.commits, nil)
end
expose :diffs, using: Entities::RepoDiff do |compare, options|
2017-05-31 15:41:25 -04:00
compare.diffs(limits: false).to_a
end
expose :compare_timeout do |compare, options|
2016-03-03 12:38:44 -05:00
compare.diffs.overflow?
end
expose :same, as: :compare_same_ref
end
2014-07-02 08:09:06 -04:00
class Contributor < Grape::Entity
expose :name, :email, :commits, :additions, :deletions
end
2015-02-07 10:41:30 -05:00
class BroadcastMessage < Grape::Entity
expose :message, :starts_at, :ends_at, :color, :font
end
class ApplicationSetting < Grape::Entity
expose :id
expose(*::ApplicationSettingsHelper.visible_attributes)
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) }
expose :password_authentication_enabled, as: :signin_enabled
end
class Release < Grape::Entity
expose :tag, as: :tag_name
expose :description
end
class RepoTag < Grape::Entity
expose :name, :message
expose :commit, using: Entities::RepoCommit do |repo_tag, options|
options[:project].repository.commit(repo_tag.dereferenced_target)
end
expose :release, using: Entities::Release do |repo_tag, options|
options[:project].releases.find_by(tag: repo_tag.name)
end
end
2015-12-10 12:04:40 -05:00
2016-01-08 16:57:42 -05:00
class Runner < Grape::Entity
2015-12-28 07:09:51 -05:00
expose :id
expose :description
expose :active
expose :is_shared
expose :name
end
class RunnerDetails < Runner
expose :tag_list
expose :run_untagged
expose :locked
expose :version, :revision, :platform, :architecture
expose :contacted_at
2017-04-08 22:20:57 -04:00
expose :token, if: lambda { |runner, options| options[:current_user].admin? || !runner.is_shared? }
expose :projects, with: Entities::BasicProjectDetails do |runner, options|
2017-04-08 22:20:57 -04:00
if options[:current_user].admin?
runner.projects
else
options[:current_user].authorized_projects.where(id: runner.projects)
end
end
end
2017-02-14 17:52:02 -05:00
class RunnerRegistrationDetails < Grape::Entity
expose :id, :token
end
class JobArtifactFile < Grape::Entity
expose :filename, :size
end
class PipelineBasic < Grape::Entity
expose :id, :sha, :ref, :status
end
class Job < Grape::Entity
2016-01-11 05:15:04 -05:00
expose :id, :status, :stage, :name, :ref, :tag, :coverage
2016-01-08 16:57:42 -05:00
expose :created_at, :started_at, :finished_at
2016-01-12 12:32:18 -05:00
expose :user, with: User
2017-03-06 03:31:37 -05:00
expose :artifacts_file, using: JobArtifactFile, if: -> (job, opts) { job.artifacts? }
expose :commit, with: RepoCommit
2016-01-08 16:57:42 -05:00
expose :runner, with: Runner
expose :pipeline, with: PipelineBasic
end
2016-01-04 10:38:32 -05:00
class Trigger < Grape::Entity
2017-03-05 15:18:00 -05:00
expose :id
2017-03-05 14:58:08 -05:00
expose :token, :description
expose :created_at, :updated_at, :deleted_at, :last_used
expose :owner, using: Entities::UserBasic
2016-01-04 10:38:32 -05:00
end
class Variable < Grape::Entity
2016-01-07 08:10:49 -05:00
expose :key, :value
2017-05-25 07:49:46 -04:00
expose :protected?, as: :protected
end
class Pipeline < PipelineBasic
expose :before_sha, :tag, :yaml_errors
2016-08-17 04:09:42 -04:00
expose :user, with: Entities::UserBasic
expose :created_at, :updated_at, :started_at, :finished_at, :committed_at
expose :duration
expose :coverage
2016-08-17 04:09:42 -04:00
end
2017-05-11 15:12:04 -04:00
class PipelineSchedule < Grape::Entity
expose :id
expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active
expose :created_at, :updated_at
2017-05-11 15:12:04 -04:00
expose :owner, using: Entities::UserBasic
end
2017-05-27 08:29:01 -04:00
class PipelineScheduleDetails < PipelineSchedule
expose :last_pipeline, using: Entities::PipelineBasic
end
class EnvironmentBasic < Grape::Entity
2016-12-07 20:09:18 -05:00
expose :id, :name, :slug, :external_url
2016-07-26 03:37:02 -04:00
end
class Environment < EnvironmentBasic
expose :project, using: Entities::BasicProjectDetails
2016-08-16 02:45:23 -04:00
end
class Deployment < Grape::Entity
expose :id, :iid, :ref, :sha, :created_at
2016-08-18 15:10:20 -04:00
expose :user, using: Entities::UserBasic
expose :environment, using: Entities::EnvironmentBasic
expose :deployable, using: Entities::Job
2016-07-26 03:37:02 -04:00
end
class RepoLicense < Grape::Entity
expose :key, :name, :nickname
expose :featured, as: :popular
expose :url, as: :html_url
expose(:source_url) { |license| license.meta['source'] }
expose(:description) { |license| license.meta['description'] }
expose(:conditions) { |license| license.meta['conditions'] }
expose(:permissions) { |license| license.meta['permissions'] }
expose(:limitations) { |license| license.meta['limitations'] }
expose :content
end
2016-04-29 10:25:03 -04:00
2016-05-27 05:00:56 -04:00
class TemplatesList < Grape::Entity
2016-04-29 10:25:03 -04:00
expose :name
end
2016-05-27 05:00:56 -04:00
class Template < Grape::Entity
2016-04-29 10:25:03 -04:00
expose :name, :content
end
class BroadcastMessage < Grape::Entity
expose :id, :message, :starts_at, :ends_at, :color, :font
expose :active?, as: :active
end
2017-02-15 12:08:29 -05:00
class PersonalAccessToken < Grape::Entity
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
class PersonalAccessTokenWithToken < PersonalAccessToken
expose :token
end
class ImpersonationToken < PersonalAccessTokenWithToken
expose :impersonation
end
2017-05-31 17:06:01 -04:00
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
2017-02-15 19:05:44 -05:00
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
2017-02-15 12:08:29 -05:00
2017-02-15 19:05:44 -05:00
class RunnerInfo < Grape::Entity
expose :timeout
end
2017-02-15 12:08:29 -05:00
2017-02-15 19:05:44 -05:00
class Step < Grape::Entity
2017-02-27 10:05:44 -05:00
expose :name, :script, :timeout, :when, :allow_failure
2017-02-15 19:05:44 -05:00
end
2017-02-15 12:08:29 -05:00
2017-02-15 19:05:44 -05:00
class Image < Grape::Entity
expose :name, :entrypoint
end
class Service < Image
expose :alias, :command
2017-02-15 19:05:44 -05:00
end
2017-02-15 12:08:29 -05:00
2017-02-15 19:05:44 -05:00
class Artifacts < Grape::Entity
expose :name, :untracked, :paths, :when, :expire_in
2017-02-15 12:08:29 -05:00
end
2017-02-15 19:05:44 -05:00
class Cache < Grape::Entity
2017-06-27 10:38:12 -04:00
expose :key, :untracked, :paths, :policy
2017-02-15 12:08:29 -05:00
end
2017-02-15 19:05:44 -05:00
class Credentials < Grape::Entity
expose :type, :url, :username, :password
end
2017-02-15 12:08:29 -05:00
2017-02-15 19:05:44 -05:00
class ArtifactFile < Grape::Entity
expose :filename, :size
end
class Dependency < Grape::Entity
expose :id, :name, :token
2017-02-15 19:05:44 -05:00
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
expose :services, using: Service
2017-02-15 19:05:44 -05:00
expose :artifacts, using: Artifacts
expose :cache, using: Cache
expose :credentials, using: Credentials
expose :dependencies, using: Dependency
2017-02-15 19:05:44 -05:00
end
2017-02-15 12:08:29 -05:00
end
class UserAgentDetail < Grape::Entity
expose :user_agent
expose :ip_address
2017-07-06 09:19:14 -04:00
expose :submitted, as: :akismet_submitted
end
2017-05-17 12:17:15 -04:00
class RepositoryStorageHealth < Grape::Entity
expose :storage_name
expose :failing_on_hosts
expose :total_failures
end
2012-06-27 07:32:56 -04:00
end
end