Commit 1c542e28 authored by Valery Sizov's avatar Valery Sizov

Merge branch 'master' of dev.gitlab.org:gitlab/gitlab-ee

parents ace64666 8bcebf17
Please view this file on the master branch, on stable branches it's out of date.
v 8.1.0
- Fix: LDAP group links API is not working as expected.
v 8.0.1
- Improve CI migration procedure and documentation
......
v 8.1.0 (unreleased)
- added an issues template (Hannes Rosenögger)
v 8.1.0
- Add documentation for "Share project with group" API call
- Abiliy to disable 'Share with Group' feature (via UI and API)
v 8.0.1
- Correct gem dependency versions
......
......@@ -135,7 +135,7 @@ class GroupsController < Groups::ApplicationController
end
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
def load_events
......
......@@ -5,6 +5,7 @@ class LdapGroupLink < ActiveRecord::Base
validates :cn, :group_access, :group_id, presence: true
validates :cn, uniqueness: { scope: [:group_id, :provider] }
validates :group_access, inclusion: { in: Gitlab::Access.all_values }
validates :provider, presence: true
scope :with_provider, ->(provider) { where(provider: provider) }
......
......@@ -777,4 +777,8 @@ class Project < ActiveRecord::Base
approvers.find_or_create_by(user_id: user_id, target_id: id)
end
end
def allowed_to_share_with_group?
!namespace.share_with_group_lock
end
end
......@@ -145,7 +145,7 @@ class ProjectTeam
access << group.group_members.find_by(user_id: user_id).try(:access_field)
end
if project.invited_groups.any?
if project.invited_groups.any? && project.allowed_to_share_with_group?
access << max_invited_level(user_id)
end
......@@ -175,7 +175,7 @@ class ProjectTeam
group_members = group ? group.group_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|
invited_group = group_link.group
im = invited_group.group_members
......
......@@ -27,13 +27,22 @@
.form-group
%hr
= f.label :name, class: 'control-label' do
= f.label :membership_lock, class: 'control-label' do
Member lock
.col-sm-10
.checkbox
= f.check_box :membership_lock
%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
= f.submit 'Save group', class: "btn btn-save"
......
......@@ -13,6 +13,7 @@
= icon('pencil-square-o fw')
%span
Project Settings
- if @project.allowed_to_share_with_group?
= nav_link(controller: :group_links) do
= link_to namespace_project_group_links_path(@project.namespace, @project) do
= icon('share-square-o fw')
......
......@@ -32,7 +32,7 @@
- if @group
= 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"
:coffeescript
......
class AddGroupShareLock < ActiveRecord::Migration
def change
add_column :namespaces, :share_with_group_lock, :boolean, default: false
end
end
class UpdateGroupLinks < ActiveRecord::Migration
def change
provider = quote_string(Gitlab::LDAP::Config.providers.first)
execute("UPDATE ldap_group_links SET provider = '#{provider}' WHERE provider IS NULL")
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150929160851) do
ActiveRecord::Schema.define(version: 20151008130321) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -58,7 +58,6 @@ ActiveRecord::Schema.define(version: 20150929160851) do
t.integer "session_expire_delay", default: 10080, null: false
t.text "import_sources"
t.text "help_page_text"
t.boolean "ci_enabled", default: true, null: false
end
create_table "approvals", force: true do |t|
......@@ -130,8 +129,18 @@ ActiveRecord::Schema.define(version: 20150929160851) do
t.boolean "allow_failure", default: false, null: false
t.string "stage"
t.integer "trigger_request_id"
t.integer "stage_idx"
t.boolean "tag"
t.string "ref"
t.integer "user_id"
t.string "type"
t.string "target_url"
t.string "description"
end
add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree
add_index "ci_builds", ["commit_id", "type", "name", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_name_and_ref", using: :btree
add_index "ci_builds", ["commit_id", "type", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_ref", using: :btree
add_index "ci_builds", ["commit_id"], name: "index_ci_builds_on_commit_id", using: :btree
add_index "ci_builds", ["project_id", "commit_id"], name: "index_ci_builds_on_project_id_and_commit_id", using: :btree
add_index "ci_builds", ["project_id"], name: "index_ci_builds_on_project_id", using: :btree
......@@ -148,6 +157,7 @@ ActiveRecord::Schema.define(version: 20150929160851) do
t.boolean "tag", default: false
t.text "yaml_errors"
t.datetime "committed_at"
t.integer "gl_project_id"
end
add_index "ci_commits", ["project_id", "committed_at", "id"], name: "index_ci_commits_on_project_id_and_committed_at_and_id", using: :btree
......@@ -187,7 +197,7 @@ ActiveRecord::Schema.define(version: 20150929160851) do
add_index "ci_jobs", ["project_id"], name: "index_ci_jobs_on_project_id", using: :btree
create_table "ci_projects", force: true do |t|
t.string "name", null: false
t.string "name"
t.integer "timeout", default: 3600, null: false
t.datetime "created_at"
t.datetime "updated_at"
......@@ -519,6 +529,7 @@ ActiveRecord::Schema.define(version: 20150929160851) do
t.integer "position", default: 0
t.datetime "locked_at"
t.integer "updated_by_id"
t.string "merge_error"
end
add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree
......@@ -558,6 +569,7 @@ ActiveRecord::Schema.define(version: 20150929160851) do
t.string "description", default: "", null: false
t.string "avatar"
t.boolean "membership_lock", default: false
t.boolean "share_with_group_lock", default: false
end
add_index "namespaces", ["created_at", "id"], name: "index_namespaces_on_created_at_and_id", using: :btree
......@@ -834,6 +846,7 @@ ActiveRecord::Schema.define(version: 20150929160851) do
t.integer "dashboard", default: 0
t.integer "project_view", default: 0
t.integer "consumed_timestep"
t.integer "layout", default: 0
end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
......
......@@ -46,6 +46,24 @@ 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
## 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
......
......@@ -477,6 +477,20 @@ Revoking team membership for a user who is not currently a team member is consid
Please note that the returned JSON currently differs slightly. Thus you should not
rely on the returned JSON structure.
### Share project with group
Allow to share project with group.
```
POST /projects/:id/share
```
Parameters:
- `id` (required) - The ID of a project
- `group_id` (required) - The ID of a group
- `group_access` (required) - Level of permissions for sharing
## Hooks
Also called Project Hooks and Webhooks.
......
......@@ -25,13 +25,16 @@ module API
# Parameters:
# 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:
# POST /groups
post do
authorize! :create_group, current_user
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)
if @group.save
......@@ -51,6 +54,29 @@ module API
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
#
# Parameters:
......
......@@ -265,6 +265,10 @@ module API
authorize! :admin_project, user_project
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.group_id = params[:group_id]
link.group_access = params[:group_access]
......
......@@ -418,4 +418,17 @@ describe Project do
it { should eq "http://localhost#{avatar_path}" }
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
......@@ -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(nonmember.id)).to be_nil }
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
......@@ -142,6 +142,24 @@ describe API::API, api: true do
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
context "when authenticated as user" do
it "should remove group" do
......
......@@ -655,6 +655,12 @@ describe API::API, api: true do
expect(response.status).to eq 400
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
post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: 1234
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