Commit b7cc9bb5 authored by Valery Sizov's avatar Valery Sizov

Abiliy to disable 'Share with Group' feature

parent e5fde8a4
v 8.1.0 v 8.1.0
- Add documentation for "Share project with group" API call - Add documentation for "Share project with group" API call
- Abiliy to disable 'Share with Group' feature (via UI and API)
v 8.0.1 v 8.0.1
- Correct gem dependency versions - Correct gem dependency versions
......
...@@ -135,7 +135,7 @@ class GroupsController < Groups::ApplicationController ...@@ -135,7 +135,7 @@ class GroupsController < Groups::ApplicationController
end end
def group_params def group_params
params.require(:group).permit(:name, :description, :path, :avatar, :membership_lock) params.require(:group).permit(:name, :description, :path, :avatar, :membership_lock, :share_with_group_lock)
end end
def load_events def load_events
......
...@@ -777,4 +777,8 @@ class Project < ActiveRecord::Base ...@@ -777,4 +777,8 @@ class Project < ActiveRecord::Base
approvers.find_or_create_by(user_id: user_id, target_id: id) approvers.find_or_create_by(user_id: user_id, target_id: id)
end end
end end
def allowed_to_share_with_group?
!namespace.share_with_group_lock
end
end end
...@@ -145,7 +145,7 @@ class ProjectTeam ...@@ -145,7 +145,7 @@ class ProjectTeam
access << group.group_members.find_by(user_id: user_id).try(:access_field) access << group.group_members.find_by(user_id: user_id).try(:access_field)
end end
if project.invited_groups.any? if project.invited_groups.any? && project.allowed_to_share_with_group?
access << max_invited_level(user_id) access << max_invited_level(user_id)
end end
...@@ -175,7 +175,7 @@ class ProjectTeam ...@@ -175,7 +175,7 @@ class ProjectTeam
group_members = group ? group.group_members : [] group_members = group ? group.group_members : []
invited_members = [] invited_members = []
if project.invited_groups.any? if project.invited_groups.any? && project.allowed_to_share_with_group?
project.project_group_links.each do |group_link| project.project_group_links.each do |group_link|
invited_group = group_link.group invited_group = group_link.group
im = invited_group.group_members im = invited_group.group_members
......
...@@ -27,13 +27,22 @@ ...@@ -27,13 +27,22 @@
.form-group .form-group
%hr %hr
= f.label :name, class: 'control-label' do = f.label :membership_lock, class: 'control-label' do
Member lock Member lock
.col-sm-10 .col-sm-10
.checkbox .checkbox
= f.check_box :membership_lock = f.check_box :membership_lock
%span.descr Prevent adding new members to project membership within this group %span.descr Prevent adding new members to project membership within this group
.form-group
%hr
= f.label :share_with_group_lock, class: 'control-label' do
Share with group lock
.col-sm-10
.checkbox
= f.check_box :share_with_group_lock
%span.descr Prevent sharing a project with another group within this group
.form-actions .form-actions
= f.submit 'Save group', class: "btn btn-save" = f.submit 'Save group', class: "btn btn-save"
......
...@@ -13,11 +13,12 @@ ...@@ -13,11 +13,12 @@
= icon('pencil-square-o fw') = icon('pencil-square-o fw')
%span %span
Project Settings Project Settings
= nav_link(controller: :group_links) do - if @project.allowed_to_share_with_group?
= link_to namespace_project_group_links_path(@project.namespace, @project) do = nav_link(controller: :group_links) do
= icon('share-square-o fw') = link_to namespace_project_group_links_path(@project.namespace, @project) do
%span = icon('share-square-o fw')
Groups %span
Groups
= nav_link(controller: :deploy_keys) do = nav_link(controller: :deploy_keys) do
= link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys', data: {placement: 'right'} do = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys', data: {placement: 'right'} do
= icon('key fw') = icon('key fw')
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
- if @group - if @group
= render "group_members", members: @group_members = render "group_members", members: @group_members
- if @project_group_links.any? - if @project_group_links.any? && @project.allowed_to_share_with_group?
= render "shared_group_members" = render "shared_group_members"
:coffeescript :coffeescript
......
class AddGroupShareLock < ActiveRecord::Migration
def change
add_column :namespaces, :share_with_group_lock, :boolean, default: false
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150920161119) do ActiveRecord::Schema.define(version: 20150930110012) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -549,15 +549,16 @@ ActiveRecord::Schema.define(version: 20150920161119) do ...@@ -549,15 +549,16 @@ ActiveRecord::Schema.define(version: 20150920161119) do
add_index "milestones", ["project_id"], name: "index_milestones_on_project_id", using: :btree add_index "milestones", ["project_id"], name: "index_milestones_on_project_id", using: :btree
create_table "namespaces", force: true do |t| create_table "namespaces", force: true do |t|
t.string "name", null: false t.string "name", null: false
t.string "path", null: false t.string "path", null: false
t.integer "owner_id" t.integer "owner_id"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "type" t.string "type"
t.string "description", default: "", null: false t.string "description", default: "", null: false
t.string "avatar" t.string "avatar"
t.boolean "membership_lock", default: false t.boolean "membership_lock", default: false
t.boolean "share_with_group_lock", default: false
end end
add_index "namespaces", ["created_at", "id"], name: "index_namespaces_on_created_at_and_id", using: :btree add_index "namespaces", ["created_at", "id"], name: "index_namespaces_on_created_at_and_id", using: :btree
......
...@@ -46,6 +46,24 @@ Parameters: ...@@ -46,6 +46,24 @@ Parameters:
- `name` (required) - The name of the group - `name` (required) - The name of the group
- `path` (required) - The path of the group - `path` (required) - The path of the group
- `description` (optional) - The group's description - `description` (optional) - The group's description
- `membership_lock` (optional, boolean) - Prevent adding new members to project membership within this group
- `share_with_group_lock` (optional, boolean) - Prevent sharing a project with another group within this group
## Update group
Updates a project group. Available only for users who can manage this group.
```
PUT /groups/:id
```
Parameters:
- `name` (required) - The name of the group
- `path` (required) - The path of the group
- `description` (optional) - The group's description
- `membership_lock` (optional, boolean) - Prevent adding new members to project membership within this group
- `share_with_group_lock` (optional, boolean) - Prevent sharing a project with another group within this group
## Transfer project to group ## Transfer project to group
......
...@@ -23,15 +23,18 @@ module API ...@@ -23,15 +23,18 @@ module API
# Create group. Available only for users who can create groups. # Create group. Available only for users who can create groups.
# #
# Parameters: # Parameters:
# name (required) - The name of the group # name (required) - The name of the group
# path (required) - The path of the group # path (required) - The path of the group
# description (optional) - The details of the group
# membership_lock (optional, boolean) - Prevent adding new members to project membership within this group
# share_with_group_lock (optional, boolean) - Prevent sharing a project with another group within this group
# Example Request: # Example Request:
# POST /groups # POST /groups
post do post do
authorize! :create_group, current_user authorize! :create_group, current_user
required_attributes! [:name, :path] required_attributes! [:name, :path]
attrs = attributes_for_keys [:name, :path, :description] attrs = attributes_for_keys [:name, :path, :description, :membership_lock, :share_with_group_lock]
@group = Group.new(attrs) @group = Group.new(attrs)
if @group.save if @group.save
...@@ -51,6 +54,29 @@ module API ...@@ -51,6 +54,29 @@ module API
end end
end end
# Update group. Available only for users who can manage this group.
#
# Parameters:
# id (required) - The ID of a group
# name (required) - The name of the group
# path (required) - The path of the group
# description (optional) - The details of the group
# membership_lock (optional, boolean) - Prevent adding new members to project membership within this group
# share_with_group_lock (optional, boolean) - Prevent sharing a project with another group within this group
# Example Request:
# PUT /groups/:id
put ":id" do
attrs = attributes_for_keys [:name, :path, :description, :membership_lock, :share_with_group_lock]
@group = find_group(params[:id])
authorize! :admin_group, @group
if @group.update_attributes(attrs)
present @group, with: Entities::Group
else
render_api_error!("Failed to update group #{@group.errors.messages}", 400)
end
end
# Get a single group, with containing projects # Get a single group, with containing projects
# #
# Parameters: # Parameters:
......
...@@ -265,6 +265,10 @@ module API ...@@ -265,6 +265,10 @@ module API
authorize! :admin_project, user_project authorize! :admin_project, user_project
required_attributes! [:group_id, :group_access] required_attributes! [:group_id, :group_access]
unless user_project.allowed_to_share_with_group?
return render_api_error!("The project sharing with group is disabled", 400)
end
link = user_project.project_group_links.new link = user_project.project_group_links.new
link.group_id = params[:group_id] link.group_id = params[:group_id]
link.group_access = params[:group_access] link.group_access = params[:group_access]
......
...@@ -418,4 +418,17 @@ describe Project do ...@@ -418,4 +418,17 @@ describe Project do
it { should eq "http://localhost#{avatar_path}" } it { should eq "http://localhost#{avatar_path}" }
end end
end end
describe :allowed_to_share_with_group? do
let(:project) { create(:project) }
it "returns true" do
expect(project.allowed_to_share_with_group?).to be_truthy
end
it "returns false" do
project.namespace.update(share_with_group_lock: true)
expect(project.allowed_to_share_with_group?).to be_falsey
end
end
end end
...@@ -85,4 +85,29 @@ describe ProjectTeam do ...@@ -85,4 +85,29 @@ describe ProjectTeam do
it { expect(project.team.max_invited_level(reporter.id)).to eq(Gitlab::Access::REPORTER) } it { expect(project.team.max_invited_level(reporter.id)).to eq(Gitlab::Access::REPORTER) }
it { expect(project.team.max_invited_level(nonmember.id)).to be_nil } it { expect(project.team.max_invited_level(nonmember.id)).to be_nil }
end end
describe :max_member_access do
let(:group) { create(:group) }
let(:project) { create(:empty_project) }
before do
project.project_group_links.create(
group: group,
group_access: Gitlab::Access::DEVELOPER
)
group.add_user(master, Gitlab::Access::MASTER)
group.add_user(reporter, Gitlab::Access::REPORTER)
end
it { expect(project.team.max_member_access(master.id)).to eq(Gitlab::Access::DEVELOPER) }
it { expect(project.team.max_member_access(reporter.id)).to eq(Gitlab::Access::REPORTER) }
it { expect(project.team.max_member_access(nonmember.id)).to be_nil }
it "does not have an access" do
project.namespace.update(share_with_group_lock: true)
expect(project.team.max_member_access(master.id)).to be_nil
expect(project.team.max_member_access(reporter.id)).to be_nil
end
end
end end
...@@ -142,6 +142,24 @@ describe API::API, api: true do ...@@ -142,6 +142,24 @@ describe API::API, api: true do
end end
end end
describe "PUT /groups" do
context "when authenticated as user without group permissions" do
it "should not create group" do
put api("/groups/#{group2.id}", user1), attributes_for(:group)
expect(response.status).to eq(403)
end
end
context "when authenticated as user with group permissions" do
it "should update group" do
group2.update(owner: user2)
put api("/groups/#{group2.id}", user2), { name: 'Renamed' }
expect(response.status).to eq(200)
expect(group2.reload.name).to eq('Renamed')
end
end
end
describe "DELETE /groups/:id" do describe "DELETE /groups/:id" do
context "when authenticated as user" do context "when authenticated as user" do
it "should remove group" do it "should remove group" do
......
...@@ -655,6 +655,12 @@ describe API::API, api: true do ...@@ -655,6 +655,12 @@ describe API::API, api: true do
expect(response.status).to eq 400 expect(response.status).to eq 400
end end
it "should return a 400 error when sharing is disabled" do
project.namespace.update(share_with_group_lock: true)
post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: Gitlab::Access::DEVELOPER
expect(response.status).to eq 400
end
it "should return a 409 error when wrong params passed" do it "should return a 409 error when wrong params passed" do
post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: 1234 post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: 1234
expect(response.status).to eq 409 expect(response.status).to eq 409
......
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