Commit f51eb540 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'api-push-rules' into 'master'

Add more push rules to the API

Closes #493 and #948

See merge request !1022
parents 9887ff42 5da06598
---
title: Add more push rules to the API
merge_request: 1022
author: Robert Schilling
...@@ -1429,7 +1429,12 @@ Parameters: ...@@ -1429,7 +1429,12 @@ Parameters:
"project_id": 3, "project_id": 3,
"commit_message_regex": "Fixes \d +\", "commit_message_regex": "Fixes \d +\",
"deny_delete_tag": false, "deny_delete_tag": false,
"created_at": "2012-10-12T17:04:47Z" "created_at": "2012-10-12T17:04:47Z",
"member_check": false,
"prevent_secrets": false,
"author_email_regex": "",
"file_name_regex": "",
"max_file_size": 5
} }
``` ```
...@@ -1443,9 +1448,16 @@ POST /projects/:id/push_rule ...@@ -1443,9 +1448,16 @@ POST /projects/:id/push_rule
Parameters: Parameters:
- `id` (required) - The ID of a project | Attribute | Type | Required | Description |
- `deny_delete_tag` - Do not allow users to remove git tags with git push | --------- | ---- | -------- | ----------- |
- `commit_message_regex` - Commit message regex | `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
| `deny_delete_tag` | boolean | no | Deny deleting a tag |
| `member_check` | boolean | no | Restrict commits by author (email) to existing GitLab users |
| `prevent_secrets` | boolean | no | GitLab will reject any files that are likely to contain secrets |
| `commit_message_regex` | string | no | All commit messages must match this, e.g. `Fixed \d+\..*` |
| `author_email_regex` | string | no | All commit author emails must match this, e.g. `@my-company.com$` |
| `file_name_regex` | string | no | All commited filenames must **not** match this, e.g. `(jar|exe)$` |
| `max_file_size` | integer | no | Maximum file size (MB) |
### Edit project push rule ### Edit project push rule
...@@ -1457,9 +1469,16 @@ PUT /projects/:id/push_rule ...@@ -1457,9 +1469,16 @@ PUT /projects/:id/push_rule
Parameters: Parameters:
- `id` (required) - The ID of a project | Attribute | Type | Required | Description |
- `deny_delete_tag` - Do not allow users to remove git tags with git push | --------- | ---- | -------- | ----------- |
- `commit_message_regex` - Commit message regex | `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
| `deny_delete_tag` | boolean | no | Deny deleting a tag |
| `member_check` | boolean | no | Restrict commits by author (email) to existing GitLab users |
| `prevent_secrets` | boolean | no | GitLab will reject any files that are likely to contain secrets |
| `commit_message_regex` | string | no | All commit messages must match this, e.g. `Fixed \d+\..*` |
| `author_email_regex` | string | no | All commit author emails must match this, e.g. `@my-company.com$` |
| `file_name_regex` | string | no | All commited filenames must **not** match this, e.g. `(jar|exe)$` |
| `max_file_size` | integer | no | Maximum file size (MB) |
### Delete project push rule ### Delete project push rule
......
...@@ -60,6 +60,8 @@ module API ...@@ -60,6 +60,8 @@ module API
class ProjectPushRule < Grape::Entity class ProjectPushRule < Grape::Entity
expose :id, :project_id, :created_at expose :id, :project_id, :created_at
expose :commit_message_regex, :deny_delete_tag expose :commit_message_regex, :deny_delete_tag
expose :member_check, :prevent_secrets, :author_email_regex
expose :file_name_regex, :max_file_size
end end
class BasicProjectDetails < Grape::Entity class BasicProjectDetails < Grape::Entity
......
module API module API
# Projects push rule API
class ProjectPushRule < Grape::API class ProjectPushRule < Grape::API
before { authenticate! } before { authenticate! }
before { authorize_admin_project } before { authorize_admin_project }
...@@ -10,9 +9,16 @@ module API ...@@ -10,9 +9,16 @@ module API
resource :projects do resource :projects do
helpers do helpers do
params :push_rule_params do params :push_rule_params do
optional :commit_message_regex, type: String, desc: 'The commit message regex'
optional :deny_delete_tag, type: Boolean, desc: 'Deny deleting a tag' optional :deny_delete_tag, type: Boolean, desc: 'Deny deleting a tag'
at_least_one_of :commit_message_regex, :deny_delete_tag optional :member_check, type: Boolean, desc: 'Restrict commits by author (email) to existing GitLab users'
optional :prevent_secrets, type: Boolean, desc: 'GitLab will reject any files that are likely to contain secrets'
optional :commit_message_regex, type: String, desc: 'All commit messages must match this'
optional :author_email_regex, type: String, desc: 'All commit author emails must match this'
optional :file_name_regex, type: String, desc: 'All commited filenames must not match this'
optional :max_file_size, type: Integer, desc: 'Maximum file size (MB)'
at_least_one_of :deny_delete_tag, :member_check, :prevent_secrets,
:commit_message_regex, :author_email_regex,
:file_name_regex, :max_file_size
end end
end end
......
...@@ -19,8 +19,8 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do ...@@ -19,8 +19,8 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do
context "authorized user" do context "authorized user" do
it "returns project push rule" do it "returns project push rule" do
get api("/projects/#{project.id}/push_rule", user) get api("/projects/#{project.id}/push_rule", user)
expect(response.status).to eq(200)
expect(response).to have_http_status(200)
expect(json_response).to be_an Hash expect(json_response).to be_an Hash
expect(json_response['project_id']).to eq(project.id) expect(json_response['project_id']).to eq(project.id)
end end
...@@ -29,7 +29,8 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do ...@@ -29,7 +29,8 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do
context "unauthorized user" do context "unauthorized user" do
it "does not have access to project push rule" do it "does not have access to project push rule" do
get api("/projects/#{project.id}/push_rule", user3) get api("/projects/#{project.id}/push_rule", user3)
expect(response.status).to eq(403)
expect(response).to have_http_status(403)
end end
end end
end end
...@@ -38,20 +39,35 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do ...@@ -38,20 +39,35 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do
context "authorized user" do context "authorized user" do
it "adds push rule to project" do it "adds push rule to project" do
post api("/projects/#{project.id}/push_rule", user), post api("/projects/#{project.id}/push_rule", user),
deny_delete_tag: true deny_delete_tag: true, member_check: true, prevent_secrets: true,
expect(response.status).to eq(201) commit_message_regex: 'JIRA\-\d+',
author_email_regex: '[a-zA-Z0-9]+@gitlab.com',
file_name_regex: '[a-zA-Z0-9]+.key',
max_file_size: 5
expect(json_response).to be_an Hash expect(response).to have_http_status(201)
expect(json_response['project_id']).to eq(project.id) expect(json_response['project_id']).to eq(project.id)
expect(json_response['deny_delete_tag']).to eq(true) expect(json_response['deny_delete_tag']).to eq(true)
expect(json_response['member_check']).to eq(true)
expect(json_response['prevent_secrets']).to eq(true)
expect(json_response['commit_message_regex']).to eq('JIRA\-\d+')
expect(json_response['author_email_regex']).to eq('[a-zA-Z0-9]+@gitlab.com')
expect(json_response['file_name_regex']).to eq('[a-zA-Z0-9]+.key')
expect(json_response['max_file_size']).to eq(5)
end end
end end
it 'returns 400 if no parameter is given' do
post api("/projects/#{project.id}/push_rule", user)
expect(response).to have_http_status(400)
end
context "unauthorized user" do context "unauthorized user" do
it "does not add push rule to project" do it "does not add push rule to project" do
post api("/projects/#{project.id}/push_rule", user3), post api("/projects/#{project.id}/push_rule", user3), deny_delete_tag: true
deny_delete_tag: true
expect(response.status).to eq(403) expect(response).to have_http_status(403)
end end
end end
end end
...@@ -63,9 +79,9 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do ...@@ -63,9 +79,9 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do
context "with existing push rule" do context "with existing push rule" do
it "does not add push rule to project" do it "does not add push rule to project" do
post api("/projects/#{project.id}/push_rule", user), post api("/projects/#{project.id}/push_rule", user), deny_delete_tag: true
deny_delete_tag: true
expect(response.status).to eq(422) expect(response).to have_http_status(422)
end end
end end
end end
...@@ -78,24 +94,31 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do ...@@ -78,24 +94,31 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do
it "updates an existing project push rule" do it "updates an existing project push rule" do
put api("/projects/#{project.id}/push_rule", user), put api("/projects/#{project.id}/push_rule", user),
deny_delete_tag: false, commit_message_regex: 'Fixes \d+\..*' deny_delete_tag: false, commit_message_regex: 'Fixes \d+\..*'
expect(response.status).to eq(200)
expect(response).to have_http_status(200)
expect(json_response['deny_delete_tag']).to eq(false) expect(json_response['deny_delete_tag']).to eq(false)
expect(json_response['commit_message_regex']).to eq('Fixes \d+\..*') expect(json_response['commit_message_regex']).to eq('Fixes \d+\..*')
end end
it 'returns 400 if no parameter is given' do
put api("/projects/#{project.id}/push_rule", user)
expect(response).to have_http_status(400)
end
end end
describe "PUT /projects/:id/push_rule" do describe "PUT /projects/:id/push_rule" do
it "gets error on non existing project push rule" do it "gets error on non existing project push rule" do
put api("/projects/#{project.id}/push_rule", user), put api("/projects/#{project.id}/push_rule", user),
deny_delete_tag: false, commit_message_regex: 'Fixes \d+\..*' deny_delete_tag: false, commit_message_regex: 'Fixes \d+\..*'
expect(response.status).to eq(404)
expect(response).to have_http_status(404)
end end
it "does not update push rule for unauthorized user" do it "does not update push rule for unauthorized user" do
post api("/projects/#{project.id}/push_rule", user3), post api("/projects/#{project.id}/push_rule", user3), deny_delete_tag: true
deny_delete_tag: true
expect(response.status).to eq(403) expect(response).to have_http_status(403)
end end
end end
...@@ -107,8 +130,8 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do ...@@ -107,8 +130,8 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do
context "authorized user" do context "authorized user" do
it "deletes push rule from project" do it "deletes push rule from project" do
delete api("/projects/#{project.id}/push_rule", user) delete api("/projects/#{project.id}/push_rule", user)
expect(response.status).to eq(200)
expect(response).to have_http_status(200)
expect(json_response).to be_an Hash expect(json_response).to be_an Hash
end end
end end
...@@ -116,7 +139,8 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do ...@@ -116,7 +139,8 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do
context "unauthorized user" do context "unauthorized user" do
it "returns a 403 error" do it "returns a 403 error" do
delete api("/projects/#{project.id}/push_rule", user3) delete api("/projects/#{project.id}/push_rule", user3)
expect(response.status).to eq(403)
expect(response).to have_http_status(403)
end end
end end
end end
...@@ -125,15 +149,16 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do ...@@ -125,15 +149,16 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do
context "for non existing push rule" do context "for non existing push rule" do
it "deletes push rule from project" do it "deletes push rule from project" do
delete api("/projects/#{project.id}/push_rule", user) delete api("/projects/#{project.id}/push_rule", user)
expect(response.status).to eq(404)
expect(response).to have_http_status(404)
expect(json_response).to be_an Hash expect(json_response).to be_an Hash
expect(json_response['message']).to eq('404 Push Rule Not Found') expect(json_response['message']).to eq('404 Push Rule Not Found')
end end
it "returns a 403 error if not authorized" do it "returns a 403 error if not authorized" do
delete api("/projects/#{project.id}/push_rule", user3) delete api("/projects/#{project.id}/push_rule", user3)
expect(response.status).to eq(403)
expect(response).to have_http_status(403)
end end
end end
end end
......
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