From ec20fdf366843e60ed30abb5322c3c1b8f471b4a Mon Sep 17 00:00:00 2001
From: Felipe Artur <felipefac@gmail.com>
Date: Wed, 16 Mar 2016 19:44:33 -0300
Subject: [PATCH] Code improvements and add Create group service

---
 app/assets/stylesheets/framework/common.scss  | 46 ++++++++-----------
 app/assets/stylesheets/framework/mobile.scss  |  2 +-
 app/assets/stylesheets/pages/projects.scss    | 22 ---------
 app/controllers/groups_controller.rb          |  4 +-
 app/controllers/users_controller.rb           |  9 +---
 app/finders/joined_groups_finder.rb           |  2 +-
 app/models/ability.rb                         |  4 +-
 app/services/groups/base_service.rb           |  4 ++
 app/services/groups/create_service.rb         | 17 +++++++
 app/services/groups/update_service.rb         | 13 ++----
 app/services/projects/create_service.rb       |  6 ++-
 app/views/groups/show.html.haml               |  4 +-
 app/views/projects/_home_panel.html.haml      |  2 +-
 ...roup_visibility_to_application_settings.rb | 20 +++++++-
 db/schema.rb                                  |  2 +-
 .../security/group/internal_access_spec.rb    |  2 -
 spec/services/groups/create_service_spec.rb   | 22 +++++++++
 17 files changed, 97 insertions(+), 84 deletions(-)
 create mode 100644 app/services/groups/create_service.rb
 create mode 100644 spec/services/groups/create_service_spec.rb

diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 18044b25b87..0931090b840 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -383,35 +383,25 @@ table {
   margin-right: -$gl-padding;
   border-top: 1px solid $border-color;
 }
-.message {
-  border: 1px solid #ccc;
-  padding: 10px;
-  color: #333;
-}
-.message {
-  border: 1px solid #ccc;
-  padding: 10px;
-  color: #333;
-}
 
-.group-projects-show-title{
-    h1 {
-      color: #313236;
-      margin: 0;
-      margin-bottom: 6px;
-      font-size: 23px;
-      font-weight: normal;
-    }
+.cover-title{
+  h1 {
+    color: #313236;
+    margin: 0;
+    margin-bottom: 6px;
+    font-size: 23px;
+    font-weight: normal;
+  }
 
-    .visibility-icon {
-      display: inline-block;
-      margin-left: 5px;
-      font-size: 18px;
-      color: $gray;
-    }
+  .visibility-icon {
+    display: inline-block;
+    margin-left: 5px;
+    font-size: 18px;
+    color: $gray;
+  }
 
-    p {
-      padding: 0 $gl-padding;
-      color: #5c5d5e;
-    }
+  p {
+    padding: 0 $gl-padding;
+    color: #5c5d5e;
   }
+}
diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss
index 3bfac2ad9b5..d088228fe4c 100644
--- a/app/assets/stylesheets/framework/mobile.scss
+++ b/app/assets/stylesheets/framework/mobile.scss
@@ -48,7 +48,7 @@
       display: block;
     }
 
-    .project-home-desc {
+    #project-home-desc {
       font-size: 21px;
     }
 
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index b1b76edfb32..1a7b0c1e278 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -61,28 +61,6 @@
     }
   }
 
-  .project-home-desc {
-    h1 {
-      color: #313236;
-      margin: 0;
-      margin-bottom: 6px;
-      font-size: 23px;
-      font-weight: normal;
-    }
-
-    .visibility-icon {
-      display: inline-block;
-      margin-left: 5px;
-      font-size: 18px;
-      color: $gray;
-    }
-
-    p {
-      padding: 0 $gl-padding;
-      color: #5c5d5e;
-    }
-  }
-
   .project-repo-buttons {
     margin-top: 20px;
     margin-bottom: 0px;
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 54f14e62ead..5baeb3def08 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -29,10 +29,8 @@ class GroupsController < Groups::ApplicationController
 
   def create
     @group = Group.new(group_params)
-    @group.name = @group.path.dup unless @group.name
 
-    if @group.save
-      @group.add_owner(current_user)
+    if Groups::CreateService.new(@group, current_user, group_params).execute
       redirect_to @group, notice: "Group '#{@group.name}' was successfully created."
     else
       render action: "new"
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 7b32572f822..481d00d6aae 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -3,13 +3,6 @@ class UsersController < ApplicationController
   before_action :set_user
 
   def show
-    @contributed_projects = contributed_projects.joined(@user).reject(&:forked?)
-
-    @projects = PersonalProjectsFinder.new(@user).execute(current_user)
-    @projects = @projects.page(params[:page]).per(PER_PAGE)
-
-    @groups =  JoinedGroupsFinder.new(@user).execute(current_user)
-
     respond_to do |format|
       format.html
 
@@ -115,7 +108,7 @@ class UsersController < ApplicationController
   end
 
   def load_groups
-    @groups = @user.groups.order_id_desc
+    @groups = JoinedGroupsFinder.new(@user).execute(current_user)
   end
 
   def projects_for_current_user
diff --git a/app/finders/joined_groups_finder.rb b/app/finders/joined_groups_finder.rb
index 131b518563e..fbdf492c965 100644
--- a/app/finders/joined_groups_finder.rb
+++ b/app/finders/joined_groups_finder.rb
@@ -1,6 +1,6 @@
 #Shows only authorized groups of a user
 class JoinedGroupsFinder
-  def initialize(user = nil)
+  def initialize(user)
     @user = user
   end
 
diff --git a/app/models/ability.rb b/app/models/ability.rb
index fe460ccdaca..bd001ef1545 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -295,8 +295,8 @@ class Ability
     end
 
     def can_read_group?(user, group)
-      is_project_member = ProjectsFinder.new.execute(user, group: group).any?
-      user.admin? || group.public? || group.internal? || is_project_member || group.users.include?(user)
+      user.admin? || group.public? || group.internal? || group.users.include?(user) ||
+      ProjectsFinder.new.execute(user, group: group).any?
     end
 
     def namespace_abilities(user, namespace)
diff --git a/app/services/groups/base_service.rb b/app/services/groups/base_service.rb
index 5becd475d3a..644ec7c013e 100644
--- a/app/services/groups/base_service.rb
+++ b/app/services/groups/base_service.rb
@@ -5,5 +5,9 @@ module Groups
     def initialize(group, user, params = {})
       @group, @current_user, @params = group, user, params.dup
     end
+
+    def add_error_message(message)
+      group.errors.add(:visibility_level, message)
+    end
   end
 end
diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb
new file mode 100644
index 00000000000..e2875aafb94
--- /dev/null
+++ b/app/services/groups/create_service.rb
@@ -0,0 +1,17 @@
+module Groups
+  class CreateService < Groups::BaseService
+    def execute
+      return false unless visibility_level_allowed?(params[:visibility_level])
+      @group.name = @group.path.dup unless @group.name
+      @group.save(params) && @group.add_owner(current_user)
+    end
+
+    private
+
+    def visibility_level_allowed?(level)
+      allowed = Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
+      add_error_message("Visibility level restricted by admin.") unless allowed
+      allowed
+    end
+  end
+end
diff --git a/app/services/groups/update_service.rb b/app/services/groups/update_service.rb
index acb6c529c17..a7382c1e07c 100644
--- a/app/services/groups/update_service.rb
+++ b/app/services/groups/update_service.rb
@@ -5,7 +5,8 @@
 module Groups
   class UpdateService < Groups::BaseService
     def execute
-      visibility_level_allowed?(params[:visibility_level]) ? group.update_attributes(params) : false
+      return false unless visibility_level_allowed?(params[:visibility_level])
+      group.update_attributes(params)
     end
 
     private
@@ -22,7 +23,7 @@ module Groups
     def visibility_by_project(level)
       projects_visibility = group.projects.pluck(:visibility_level)
 
-      allowed_by_projects = !projects_visibility.any?{|project_visibility| level.to_i < project_visibility }
+      allowed_by_projects = !projects_visibility.any?{ |project_visibility| level.to_i < project_visibility }
       add_error_message("Cannot be changed. There are projects with higher visibility permissions.") unless allowed_by_projects
       allowed_by_projects
     end
@@ -32,13 +33,5 @@ module Groups
       add_error_message("You are not authorized to set this permission level.") unless allowed_by_user
       allowed_by_user
     end
-
-    def add_error_message(message)
-      level_name = Gitlab::VisibilityLevel.level_name(params[:visibility_level])
-      group.errors.add(:visibility_level, message)
-    end
   end
 end
-
-
-
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 522fae79503..4c121106bda 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -12,7 +12,7 @@ module Projects
       # Make sure that the user is allowed to use the specified visibility
       # level
 
-      unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) && @project.visibility_level_allowed?(@project.visibility_level)
+      unless visibility_level_allowed?
         deny_visibility_level(@project)
         return @project
       end
@@ -100,5 +100,9 @@ module Projects
 
       @project.import_start if @project.import?
     end
+
+    def visibility_level_allowed?
+      Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) && @project.visibility_level_allowed?(@project.visibility_level)
+    end
   end
 end
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 0a8c2da7207..641191edf05 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -14,11 +14,11 @@
   .avatar-holder
     = link_to group_icon(@group), target: '_blank' do
       = image_tag group_icon(@group), class: "avatar group-avatar s90"
-  .group-projects-show-title
+  .cover-title
     %h1
       = @group.name
 
-      %span.visibility-icon.has_tooltip{data: { container: 'body', placement: 'left' }, title: "#{visibility_level_label(@group.visibility_level)} - #{project_visibility_level_description(@group.visibility_level)}"}
+      %span.visibility-icon.has_tooltip{data: { container: 'body', placement: 'left' }, title: "#{visibility_level_label(@group.visibility_level)} - #{group_visibility_description(@group)}"}
         = visibility_level_icon(@group.visibility_level, fw: false)
 
   .cover-desc.username
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index dd16f504c92..e8434b5292c 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -2,7 +2,7 @@
 .project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)}
   .project-identicon-holder
     = project_icon(@project, alt: '', class: 'project-avatar avatar s90')
-  .group-projects-show-title
+  .cover-title#project-home-desc
     %h1
       = @project.name
       %span.visibility-icon.has_tooltip{data: { container: 'body' },
diff --git a/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb b/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb
index c2bdd7b31fa..b71322376fa 100644
--- a/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb
+++ b/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb
@@ -1,11 +1,27 @@
+#Create visibility level field on DB
+#Sets default_visibility_level to value on settings if not restricted
+#If value is restricted takes higher visibility level allowed
+
 class AddDefaultGroupVisibilityToApplicationSettings < ActiveRecord::Migration
   def up
     add_column :application_settings, :default_group_visibility, :integer
-    visibility = Settings.gitlab.default_groups_features['visibility_level']
-    execute("update application_settings set default_group_visibility = #{visibility}")
+    execute("update application_settings set default_group_visibility = #{allowed_visibility_level}")
   end
 
   def down
     remove_column :application_settings, :default_group_visibility
   end
+
+  private
+  def allowed_visibility_level
+    default_visibility = Settings.gitlab.default_groups_features['visibility_level']
+    restricted_levels  = current_application_settings.restricted_visibility_levels
+    return default_visibility unless restricted_levels.present?
+
+    if restricted_levels.include?(default_visibility)
+      Gitlab::VisibilityLevel.values.select{ |vis_level| vis_level unless restricted_levels.include?(vis_level) }.last
+    else
+      default_visibility
+    end
+  end
 end
diff --git a/db/schema.rb b/db/schema.rb
index 082d681a176..292a9100d9c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20160308212903) do
+ActiveRecord::Schema.define(version: 20160309140734) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
diff --git a/spec/features/security/group/internal_access_spec.rb b/spec/features/security/group/internal_access_spec.rb
index 69a0fbb4468..4e781c23ee0 100644
--- a/spec/features/security/group/internal_access_spec.rb
+++ b/spec/features/security/group/internal_access_spec.rb
@@ -4,8 +4,6 @@ describe 'Internal group access', feature: true do
   include AccessMatchers
   include GroupAccessHelper
 
-
-
   describe 'GET /groups/:path' do
     subject { group_path(group(Gitlab::VisibilityLevel::INTERNAL)) }
 
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
new file mode 100644
index 00000000000..7dbc5297978
--- /dev/null
+++ b/spec/services/groups/create_service_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe Groups::CreateService, services: true do
+    let!(:user)    { create(:user) }
+    let!(:private_group)    { create(:group, visibility_level: Gitlab::VisibilityLevel::PRIVATE) }
+    let!(:internal_group)   { create(:group, visibility_level: Gitlab::VisibilityLevel::INTERNAL) }
+    let!(:public_group)     { create(:group, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
+
+  describe "execute" do
+    let!(:service) { described_class.new(public_group, user, visibility_level: Gitlab::VisibilityLevel::PUBLIC ) }
+    subject { service.execute }
+
+    context "create groups without restricted visibility level" do
+      it { is_expected.to be_truthy }
+    end
+
+    context "cannot create group with restricted visibility level" do
+      before { allow(current_application_settings).to receive(:restricted_visibility_levels).and_return([Gitlab::VisibilityLevel::PUBLIC]) }
+      it { is_expected.to be_falsy }
+    end
+  end
+end
-- 
GitLab