Commit 631562eb authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'groups_api' into 'master'

API: Add missing group parameters

See merge request gitlab-org/gitlab!17220
parents 2ea5e00f b944c0dd
# frozen_string_literal: true
# Add methods used by the groups API
module GroupAPICompatibility
extend ActiveSupport::Concern
def project_creation_level_str
::Gitlab::Access.project_creation_string_options.key(project_creation_level)
end
def project_creation_level_str=(value)
write_attribute(:project_creation_level, ::Gitlab::Access.project_creation_string_options.fetch(value))
end
def subgroup_creation_level_str
::Gitlab::Access.subgroup_creation_string_options.key(subgroup_creation_level)
end
def subgroup_creation_level_str=(value)
write_attribute(:subgroup_creation_level, ::Gitlab::Access.subgroup_creation_string_options.fetch(value))
end
end
...@@ -14,6 +14,7 @@ class Group < Namespace ...@@ -14,6 +14,7 @@ class Group < Namespace
include TokenAuthenticatable include TokenAuthenticatable
include WithUploads include WithUploads
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
include GroupAPICompatibility
ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10 ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10
......
---
title: 'API: Add missing group parameters'
merge_request: 17220
author: Mathieu Parent
type: added
...@@ -31,6 +31,13 @@ GET /groups ...@@ -31,6 +31,13 @@ GET /groups
"path": "foo-bar", "path": "foo-bar",
"description": "An interesting group", "description": "An interesting group",
"visibility": "public", "visibility": "public",
"share_with_group_lock": false,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"project_creation_level": "developer",
"auto_devops_enabled": null,
"subgroup_creation_level": "owner",
"emails_disabled": null,
"lfs_enabled": true, "lfs_enabled": true,
"avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg", "avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg",
"web_url": "http://localhost:3000/groups/foo-bar", "web_url": "http://localhost:3000/groups/foo-bar",
...@@ -57,6 +64,13 @@ GET /groups?statistics=true ...@@ -57,6 +64,13 @@ GET /groups?statistics=true
"path": "foo-bar", "path": "foo-bar",
"description": "An interesting group", "description": "An interesting group",
"visibility": "public", "visibility": "public",
"share_with_group_lock": false,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"project_creation_level": "developer",
"auto_devops_enabled": null,
"subgroup_creation_level": "owner",
"emails_disabled": null,
"lfs_enabled": true, "lfs_enabled": true,
"avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg", "avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg",
"web_url": "http://localhost:3000/groups/foo-bar", "web_url": "http://localhost:3000/groups/foo-bar",
...@@ -119,6 +133,13 @@ GET /groups/:id/subgroups ...@@ -119,6 +133,13 @@ GET /groups/:id/subgroups
"path": "foo-bar", "path": "foo-bar",
"description": "An interesting group", "description": "An interesting group",
"visibility": "public", "visibility": "public",
"share_with_group_lock": false,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"project_creation_level": "developer",
"auto_devops_enabled": null,
"subgroup_creation_level": "owner",
"emails_disabled": null,
"lfs_enabled": true, "lfs_enabled": true,
"avatar_url": "http://gitlab.example.com/uploads/group/avatar/1/foo.jpg", "avatar_url": "http://gitlab.example.com/uploads/group/avatar/1/foo.jpg",
"web_url": "http://gitlab.example.com/groups/foo-bar", "web_url": "http://gitlab.example.com/groups/foo-bar",
...@@ -434,6 +455,13 @@ Parameters: ...@@ -434,6 +455,13 @@ Parameters:
| `path` | string | yes | The path of the group. | | `path` | string | yes | The path of the group. |
| `description` | string | no | The group's description. | | `description` | string | no | The group's description. |
| `visibility` | string | no | The group's visibility. Can be `private`, `internal`, or `public`. | | `visibility` | string | no | The group's visibility. Can be `private`, `internal`, or `public`. |
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (Maintainers), or `developer` (Developers + Maintainers). |
| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
| `subgroup_creation_level` | integer | no | Allowed to create subgroups. Can be `owner` (Owners), or `maintainer` (Maintainers). |
| `emails_disabled` | boolean | no | Disable email notifications |
| `lfs_enabled` | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. | | `lfs_enabled` | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
| `request_access_enabled` | boolean | no | Allow users to request member access. | | `request_access_enabled` | boolean | no | Allow users to request member access. |
| `parent_id` | integer | no | The parent group ID for creating nested group. | | `parent_id` | integer | no | The parent group ID for creating nested group. |
...@@ -472,6 +500,13 @@ PUT /groups/:id ...@@ -472,6 +500,13 @@ PUT /groups/:id
| `membership_lock` | boolean | no | **(STARTER)** Prevent adding new members to project membership within this group. | | `membership_lock` | boolean | no | **(STARTER)** Prevent adding new members to project membership within this group. |
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. | | `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
| `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. | | `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. |
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (Maintainers), or `developer` (Developers + Maintainers). |
| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
| `subgroup_creation_level` | integer | no | Allowed to create subgroups. Can be `owner` (Owners), or `maintainer` (Maintainers). |
| `emails_disabled` | boolean | no | Disable email notifications |
| `lfs_enabled` (optional) | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. | | `lfs_enabled` (optional) | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
| `request_access_enabled` | boolean | no | Allow users to request member access. | | `request_access_enabled` | boolean | no | Allow users to request member access. |
| `file_template_project_id` | integer | no | **(PREMIUM)** The ID of a project to load custom file templates from. | | `file_template_project_id` | integer | no | **(PREMIUM)** The ID of a project to load custom file templates from. |
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
require 'spec_helper' require 'spec_helper'
describe API::Groups do describe API::Groups do
include GroupAPIHelpers
set(:group) { create(:group) } set(:group) { create(:group) }
set(:private_group) { create(:group, :private) } set(:private_group) { create(:group, :private) }
set(:project) { create(:project, group: group) } set(:project) { create(:project, group: group) }
...@@ -133,14 +135,14 @@ describe API::Groups do ...@@ -133,14 +135,14 @@ describe API::Groups do
describe "POST /groups" do describe "POST /groups" do
context "when authenticated as user with group permissions" do context "when authenticated as user with group permissions" do
it "creates an ldap_group_link if ldap_cn and ldap_access are supplied" do it "creates an ldap_group_link if ldap_cn and ldap_access are supplied" do
group_attributes = attributes_for(:group, ldap_cn: 'ldap-group', ldap_access: Gitlab::Access::DEVELOPER) group_attributes = attributes_for_group_api ldap_cn: 'ldap-group', ldap_access: Gitlab::Access::DEVELOPER
expect { post api("/groups", admin), params: group_attributes }.to change { LdapGroupLink.count }.by(1) expect { post api("/groups", admin), params: group_attributes }.to change { LdapGroupLink.count }.by(1)
end end
context 'when shared_runners_minutes_limit is given' do context 'when shared_runners_minutes_limit is given' do
context 'when the current user is not an admin' do context 'when the current user is not an admin' do
it "does not create a group with shared_runners_minutes_limit" do it "does not create a group with shared_runners_minutes_limit" do
group = attributes_for(:group, { shared_runners_minutes_limit: 133 }) group = attributes_for_group_api shared_runners_minutes_limit: 133
expect do expect do
post api("/groups", another_user), params: group post api("/groups", another_user), params: group
...@@ -152,7 +154,7 @@ describe API::Groups do ...@@ -152,7 +154,7 @@ describe API::Groups do
context 'when the current user is an admin' do context 'when the current user is an admin' do
it "creates a group with shared_runners_minutes_limit" do it "creates a group with shared_runners_minutes_limit" do
group = attributes_for(:group, { shared_runners_minutes_limit: 133 }) group = attributes_for_group_api shared_runners_minutes_limit: 133
expect do expect do
post api("/groups", admin), params: group post api("/groups", admin), params: group
......
...@@ -378,6 +378,13 @@ module API ...@@ -378,6 +378,13 @@ module API
class Group < BasicGroupDetails class Group < BasicGroupDetails
expose :path, :description, :visibility expose :path, :description, :visibility
expose :share_with_group_lock
expose :require_two_factor_authentication
expose :two_factor_grace_period
expose :project_creation_level_str, as: :project_creation_level
expose :auto_devops_enabled
expose :subgroup_creation_level_str, as: :subgroup_creation_level
expose :emails_disabled
expose :lfs_enabled?, as: :lfs_enabled expose :lfs_enabled?, as: :lfs_enabled
expose :avatar_url do |group, options| expose :avatar_url do |group, options|
group.avatar_url(only_path: false) group.avatar_url(only_path: false)
......
...@@ -11,9 +11,15 @@ module API ...@@ -11,9 +11,15 @@ module API
optional :visibility, type: String, optional :visibility, type: String,
values: Gitlab::VisibilityLevel.string_values, values: Gitlab::VisibilityLevel.string_values,
desc: 'The visibility of the group' desc: 'The visibility of the group'
optional :share_with_group_lock, type: Boolean, desc: 'Prevent sharing a project with another group within this group'
optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users in this group to setup Two-factor authentication'
optional :two_factor_grace_period, type: Integer, desc: 'Time before Two-factor authentication is enforced'
optional :project_creation_level, type: String, values: ::Gitlab::Access.project_creation_string_values, desc: 'Determine if developers can create projects in the group', as: :project_creation_level_str
optional :auto_devops_enabled, type: Boolean, desc: 'Default to Auto DevOps pipeline for all projects within this group'
optional :subgroup_creation_level, type: String, values: ::Gitlab::Access.subgroup_creation_string_values, desc: 'Allowed to create subgroups', as: :subgroup_creation_level_str
optional :emails_disabled, type: Boolean, desc: 'Disable email notifications'
optional :lfs_enabled, type: Boolean, desc: 'Enable/disable LFS for the projects in this group' optional :lfs_enabled, type: Boolean, desc: 'Enable/disable LFS for the projects in this group'
optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access' optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
optional :share_with_group_lock, type: Boolean, desc: 'Prevent sharing a project with another group within this group'
end end
params :optional_params_ee do params :optional_params_ee do
......
...@@ -103,10 +103,22 @@ module Gitlab ...@@ -103,10 +103,22 @@ module Gitlab
} }
end end
def project_creation_string_options
{
'noone' => NO_ONE_PROJECT_ACCESS,
'maintainer' => MAINTAINER_PROJECT_ACCESS,
'developer' => DEVELOPER_MAINTAINER_PROJECT_ACCESS
}
end
def project_creation_values def project_creation_values
project_creation_options.values project_creation_options.values
end end
def project_creation_string_values
project_creation_string_options.keys
end
def project_creation_level_name(name) def project_creation_level_name(name)
project_creation_options.key(name) project_creation_options.key(name)
end end
...@@ -117,6 +129,21 @@ module Gitlab ...@@ -117,6 +129,21 @@ module Gitlab
s_('SubgroupCreationlevel|Maintainers') => MAINTAINER_SUBGROUP_ACCESS s_('SubgroupCreationlevel|Maintainers') => MAINTAINER_SUBGROUP_ACCESS
} }
end end
def subgroup_creation_string_options
{
'owner' => OWNER_SUBGROUP_ACCESS,
'maintainer' => MAINTAINER_SUBGROUP_ACCESS
}
end
def subgroup_creation_values
subgroup_creation_options.values
end
def subgroup_creation_string_values
subgroup_creation_string_options.keys
end
end end
def human_access def human_access
......
require 'spec_helper' require 'spec_helper'
describe API::Groups do describe API::Groups do
include GroupAPIHelpers
include UploadHelpers include UploadHelpers
let(:user1) { create(:user, can_create_group: false) } let(:user1) { create(:user, can_create_group: false) }
...@@ -350,6 +351,13 @@ describe API::Groups do ...@@ -350,6 +351,13 @@ describe API::Groups do
expect(json_response['description']).to eq(group1.description) expect(json_response['description']).to eq(group1.description)
expect(json_response['visibility']).to eq(Gitlab::VisibilityLevel.string_level(group1.visibility_level)) expect(json_response['visibility']).to eq(Gitlab::VisibilityLevel.string_level(group1.visibility_level))
expect(json_response['avatar_url']).to eq(group1.avatar_url(only_path: false)) expect(json_response['avatar_url']).to eq(group1.avatar_url(only_path: false))
expect(json_response['share_with_group_lock']).to eq(group1.share_with_group_lock)
expect(json_response['require_two_factor_authentication']).to eq(group1.require_two_factor_authentication)
expect(json_response['two_factor_grace_period']).to eq(group1.two_factor_grace_period)
expect(json_response['auto_devops_enabled']).to eq(group1.auto_devops_enabled)
expect(json_response['emails_disabled']).to eq(group1.emails_disabled)
expect(json_response['project_creation_level']).to eq('maintainer')
expect(json_response['subgroup_creation_level']).to eq('maintainer')
expect(json_response['web_url']).to eq(group1.web_url) expect(json_response['web_url']).to eq(group1.web_url)
expect(json_response['request_access_enabled']).to eq(group1.request_access_enabled) expect(json_response['request_access_enabled']).to eq(group1.request_access_enabled)
expect(json_response['full_name']).to eq(group1.full_name) expect(json_response['full_name']).to eq(group1.full_name)
...@@ -485,11 +493,30 @@ describe API::Groups do ...@@ -485,11 +493,30 @@ describe API::Groups do
context 'when authenticated as the group owner' do context 'when authenticated as the group owner' do
it 'updates the group' do it 'updates the group' do
put api("/groups/#{group1.id}", user1), params: { name: new_group_name, request_access_enabled: true } put api("/groups/#{group1.id}", user1), params: {
name: new_group_name,
request_access_enabled: true,
project_creation_level: "noone",
subgroup_creation_level: "maintainer"
}
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(json_response['name']).to eq(new_group_name) expect(json_response['name']).to eq(new_group_name)
expect(json_response['description']).to eq('')
expect(json_response['visibility']).to eq('public')
expect(json_response['share_with_group_lock']).to eq(false)
expect(json_response['require_two_factor_authentication']).to eq(false)
expect(json_response['two_factor_grace_period']).to eq(48)
expect(json_response['auto_devops_enabled']).to eq(nil)
expect(json_response['emails_disabled']).to eq(nil)
expect(json_response['project_creation_level']).to eq("noone")
expect(json_response['subgroup_creation_level']).to eq("maintainer")
expect(json_response['request_access_enabled']).to eq(true) expect(json_response['request_access_enabled']).to eq(true)
expect(json_response['parent_id']).to eq(nil)
expect(json_response['projects']).to be_an Array
expect(json_response['projects'].length).to eq(2)
expect(json_response['shared_projects']).to be_an Array
expect(json_response['shared_projects'].length).to eq(0)
end end
it 'returns 404 for a non existing group' do it 'returns 404 for a non existing group' do
...@@ -864,7 +891,9 @@ describe API::Groups do ...@@ -864,7 +891,9 @@ describe API::Groups do
describe "POST /groups" do describe "POST /groups" do
context "when authenticated as user without group permissions" do context "when authenticated as user without group permissions" do
it "does not create group" do it "does not create group" do
post api("/groups", user1), params: attributes_for(:group) group = attributes_for_group_api
post api("/groups", user1), params: group
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
...@@ -896,7 +925,7 @@ describe API::Groups do ...@@ -896,7 +925,7 @@ describe API::Groups do
context "when authenticated as user with group permissions" do context "when authenticated as user with group permissions" do
it "creates group" do it "creates group" do
group = attributes_for(:group, { request_access_enabled: false }) group = attributes_for_group_api request_access_enabled: false
post api("/groups", user3), params: group post api("/groups", user3), params: group
...@@ -911,7 +940,7 @@ describe API::Groups do ...@@ -911,7 +940,7 @@ describe API::Groups do
it "creates a nested group" do it "creates a nested group" do
parent = create(:group) parent = create(:group)
parent.add_owner(user3) parent.add_owner(user3)
group = attributes_for(:group, { parent_id: parent.id }) group = attributes_for_group_api parent_id: parent.id
post api("/groups", user3), params: group post api("/groups", user3), params: group
......
# frozen_string_literal: true
module GroupAPIHelpers
extend self
def attributes_for_group_api(params = {})
# project_creation_level and subgroup_creation_level are Integers in the model
# but are strings in the API
attributes_for(:group, params).except(:project_creation_level, :subgroup_creation_level)
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