1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
# frozen_string_literal: true
module API
class Notes < ::API::Base
include PaginationParams
helpers ::API::Helpers::NotesHelpers
helpers Helpers::RateLimiter
before { authenticate! }
Helpers::NotesHelpers.feature_category_per_noteable_type.each do |noteable_type, feature_category|
parent_type = noteable_type.parent_class.to_s.underscore
noteables_str = noteable_type.to_s.underscore.pluralize
params do
requires :id, type: String, desc: "The ID of a #{parent_type}"
end
resource parent_type.pluralize.to_sym, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "Get a list of #{noteable_type.to_s.downcase} notes" do
success Entities::Note
end
params do
requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at',
desc: 'Return notes ordered by `created_at` or `updated_at` fields.'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return notes sorted in `asc` or `desc` order.'
optional :activity_filter, type: String, values: UserPreference::NOTES_FILTERS.stringify_keys.keys, default: 'all_notes',
desc: 'The type of notables which are returned.'
use :pagination
end
# rubocop: disable CodeReuse/ActiveRecord
get ":id/#{noteables_str}/:noteable_id/notes", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
# We exclude notes that are cross-references and that cannot be viewed
# by the current user. By doing this exclusion at this level and not
# at the DB query level (which we cannot in that case), the current
# page can have less elements than :per_page even if
# there's more than one page.
notes_filter = UserPreference::NOTES_FILTERS[params[:activity_filter].to_sym]
raw_notes = noteable.notes.with_metadata.with_notes_filter(notes_filter).reorder(order_options_with_tie_breaker)
# paginate() only works with a relation. This could lead to a
# mismatch between the pagination headers info and the actual notes
# array returned, but this is really a edge-case.
notes = paginate(raw_notes)
notes = prepare_notes_for_rendering(notes)
notes = notes.select { |note| note.readable_by?(current_user) }
present notes, with: Entities::Note
end
# rubocop: enable CodeReuse/ActiveRecord
desc "Get a single #{noteable_type.to_s.downcase} note" do
success Entities::Note
end
params do
requires :note_id, type: Integer, desc: 'The ID of a note'
requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
end
get ":id/#{noteables_str}/:noteable_id/notes/:note_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
get_note(noteable, params[:note_id])
end
desc "Create a new #{noteable_type.to_s.downcase} note" do
success Entities::Note
end
params do
requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
requires :body, type: String, desc: 'The content of a note'
optional :confidential, type: Boolean, desc: 'Confidentiality note flag, default is false'
optional :created_at, type: String, desc: 'The creation date of the note'
end
post ":id/#{noteables_str}/:noteable_id/notes", feature_category: feature_category do
allowlist =
Gitlab::CurrentSettings.current_application_settings.notes_create_limit_allowlist
check_rate_limit! :notes_create, [current_user], allowlist
noteable = find_noteable(noteable_type, params[:noteable_id])
opts = {
note: params[:body],
noteable_type: noteables_str.classify,
noteable_id: noteable.id,
confidential: params[:confidential],
created_at: params[:created_at]
}
note = create_note(noteable, opts)
if note.errors.keys == [:commands_only]
status 202
present note, with: Entities::NoteCommands
elsif note.valid?
present note, with: Entities.const_get(note.class.name, false)
else
note.errors.delete(:commands_only) if note.errors.has_key?(:commands)
bad_request!("Note #{note.errors.messages}")
end
end
desc "Update an existing #{noteable_type.to_s.downcase} note" do
success Entities::Note
end
params do
requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
requires :note_id, type: Integer, desc: 'The ID of a note'
optional :body, type: String, allow_blank: false, desc: 'The content of a note'
optional :confidential, type: Boolean, desc: 'Confidentiality note flag'
end
put ":id/#{noteables_str}/:noteable_id/notes/:note_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
update_note(noteable, params[:note_id])
end
desc "Delete a #{noteable_type.to_s.downcase} note" do
success Entities::Note
end
params do
requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
requires :note_id, type: Integer, desc: 'The ID of a note'
end
delete ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
noteable = find_noteable(noteable_type, params[:noteable_id])
delete_note(noteable, params[:note_id])
end
end
end
end
end
|