Commit a872a29e authored by Rémy Coutable's avatar Rémy Coutable

Merge branch 'api-issue-update-and-note-create-backdating-14947' into 'master'

API issue update and note create back dating

Closes #14947 

See merge request !3551
parents 091c77e3 c1467f5d
Pipeline #1798308 passed with stage
......@@ -18,11 +18,12 @@ v 8.7.0 (unreleased)
- Preserve time notes/comments have been updated at when moving issue
- Make HTTP(s) label consistent on clone bar (Stan Hu)
- Expose label description in API (Mariusz Jachimowicz)
- Allow back dating on issues when created through the API
- API: Ability to update a group (Robert Schilling)
- API: Ability to move issues (Robert Schilling)
- Fix Error 500 after renaming a project path (Stan Hu)
- Fix a bug whith trailing slash in teamcity_url (Charles May)
- Allow back dating on issues when created or updated through the API
- Allow back dating on issue notes when created through the API
- Fix avatar stretching by providing a cropping feature
- API: Expose `subscribed` for issues and merge requests (Robert Schilling)
- Allow SAML to handle external users based on user's information !3530
......
......@@ -298,6 +298,7 @@ PUT /projects/:id/issues/:issue_id
| `milestone_id` | integer | no | The ID of a milestone to assign the issue to |
| `labels` | string | no | Comma-separated label names for an issue |
| `state_event` | string | no | The state event of an issue. Set `close` to close the issue and `reopen` to reopen it |
| `updated_at` | string | no | Date time string, ISO 8601 formatted, e.g. `2016-03-11T03:45:40Z` |
```bash
curl -X PUT -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/4/issues/85?state_event=close
......
......@@ -89,6 +89,7 @@ Parameters:
- `id` (required) - The ID of a project
- `issue_id` (required) - The ID of an issue
- `body` (required) - The content of a note
- `created_at` (optional) - Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z
### Modify existing issue note
......
......@@ -117,7 +117,7 @@ module API
# assignee_id (optional) - The ID of a user to assign issue
# milestone_id (optional) - The ID of a milestone to assign issue
# labels (optional) - The labels of an issue
# created_at (optional) - The date
# created_at (optional) - Date time string, ISO 8601 formatted
# Example Request:
# POST /projects/:id/issues
post ":id/issues" do
......@@ -166,12 +166,15 @@ module API
# milestone_id (optional) - The ID of a milestone to assign issue
# labels (optional) - The labels of an issue
# state_event (optional) - The state event of an issue (close|reopen)
# updated_at (optional) - Date time string, ISO 8601 formatted
# Example Request:
# PUT /projects/:id/issues/:issue_id
put ":id/issues/:issue_id" do
issue = user_project.issues.find(params[:issue_id])
authorize! :update_issue, issue
attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :state_event]
keys = [:title, :description, :assignee_id, :milestone_id, :state_event]
keys << :updated_at if current_user.admin? || user_project.owner == current_user
attrs = attributes_for_keys(keys)
# Validate label names in advance
if (errors = validate_label_params(params)).any?
......
......@@ -61,6 +61,7 @@ module API
# id (required) - The ID of a project
# noteable_id (required) - The ID of an issue or snippet
# body (required) - The content of a note
# created_at (optional) - The date
# Example Request:
# POST /projects/:id/issues/:noteable_id/notes
# POST /projects/:id/snippets/:noteable_id/notes
......@@ -73,6 +74,10 @@ module API
noteable_id: params[noteable_id_str]
}
if params[:created_at] && (current_user.is_admin? || user_project.owner == current_user)
opts[:created_at] = params[:created_at]
end
@note = ::Notes::CreateService.new(user_project, current_user, opts).execute
if @note.valid?
......
......@@ -321,13 +321,13 @@ describe API::API, api: true do
end
context 'when an admin or owner makes the request' do
it "accepts the creation date to be set" do
it 'accepts the creation date to be set' do
creation_time = 2.weeks.ago
post api("/projects/#{project.id}/issues", user),
title: 'new issue', labels: 'label, label2', created_at: 2.weeks.ago
title: 'new issue', labels: 'label, label2', created_at: creation_time
expect(response.status).to eq(201)
# this take about a second, so probably not equal
expect(Time.parse(json_response['created_at'])).to be <= 2.weeks.ago
expect(Time.parse(json_response['created_at'])).to be_within(1.second).of(creation_time)
end
end
end
......@@ -478,6 +478,18 @@ describe API::API, api: true do
expect(json_response['labels']).to include 'label2'
expect(json_response['state']).to eq "closed"
end
context 'when an admin or owner makes the request' do
it 'accepts the update date to be set' do
update_time = 2.weeks.ago
put api("/projects/#{project.id}/issues/#{issue.id}", user),
labels: 'label3', state_event: 'close', updated_at: update_time
expect(response.status).to eq(200)
expect(json_response['labels']).to include 'label3'
expect(Time.parse(json_response['updated_at'])).to be_within(1.second).of(update_time)
end
end
end
describe "DELETE /projects/:id/issues/:issue_id" do
......
......@@ -158,6 +158,19 @@ describe API::API, api: true do
post api("/projects/#{project.id}/issues/#{issue.id}/notes"), body: 'hi!'
expect(response.status).to eq(401)
end
context 'when an admin or owner makes the request' do
it 'accepts the creation date to be set' do
creation_time = 2.weeks.ago
post api("/projects/#{project.id}/issues/#{issue.id}/notes", user),
body: 'hi!', created_at: creation_time
expect(response.status).to eq(201)
expect(json_response['body']).to eq('hi!')
expect(json_response['author']['username']).to eq(user.username)
expect(Time.parse(json_response['created_at'])).to be_within(1.second).of(creation_time)
end
end
end
context "when noteable is a Snippet" do
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment