Commit c9def945d4222eeb8026a0311495259bf99267a1

Authored by Dmitriy Zaporozhets
1 parent c0df0cd7

User blocking improved. Admin area styled

1 v 2.4.0 1 v 2.4.0
  2 + - Ability to block user
  3 + - Simplified dashboard area
  4 + - Improved admin area
2 - Accept merge request 5 - Accept merge request
  6 + - Bootstrap 2.0
  7 + - Responsive layout
  8 + - Big commits handling
  9 + - Perfomance improved
  10 + - Milestones
3 11
4 v 2.3.1 12 v 2.3.1
5 - Issues pagination 13 - Issues pagination
app/assets/stylesheets/gitlab_bootstrap.scss
@@ -450,3 +450,17 @@ form { @@ -450,3 +450,17 @@ form {
450 } 450 }
451 451
452 } 452 }
  453 +
  454 +table.admin-table {
  455 + @extend .table-bordered;
  456 + @extend .zebra-striped;
  457 + th {
  458 + border-color: #CCC;
  459 + border-bottom: 1px solid #bbb;
  460 + background:#eee;
  461 + background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
  462 + background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
  463 + background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
  464 + background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
  465 + }
  466 +}
app/controllers/admin/users_controller.rb
@@ -4,7 +4,9 @@ class Admin::UsersController < ApplicationController @@ -4,7 +4,9 @@ class Admin::UsersController < ApplicationController
4 before_filter :authenticate_admin! 4 before_filter :authenticate_admin!
5 5
6 def index 6 def index
7 - @admin_users = User.page(params[:page]) 7 + @admin_users = User.scoped
  8 + @admin_users = @admin_users.filter(params[:filter])
  9 + @admin_users = @admin_users.order("updated_at DESC").page(params[:page])
8 end 10 end
9 11
10 def show 12 def show
@@ -38,13 +40,31 @@ class Admin::UsersController < ApplicationController @@ -38,13 +40,31 @@ class Admin::UsersController < ApplicationController
38 @admin_user = User.find(params[:id]) 40 @admin_user = User.find(params[:id])
39 end 41 end
40 42
  43 + def block
  44 + @admin_user = User.find(params[:id])
  45 +
  46 + if @admin_user.block
  47 + redirect_to :back, alert: "Successfully blocked"
  48 + else
  49 + redirect_to :back, alert: "Error occured. User was not blocked"
  50 + end
  51 + end
  52 +
  53 + def unblock
  54 + @admin_user = User.find(params[:id])
  55 +
  56 + if @admin_user.update_attribute(:blocked, false)
  57 + redirect_to :back, alert: "Successfully unblocked"
  58 + else
  59 + redirect_to :back, alert: "Error occured. User was not unblocked"
  60 + end
  61 + end
  62 +
41 def create 63 def create
42 admin = params[:user].delete("admin") 64 admin = params[:user].delete("admin")
43 - blocked = params[:user].delete("blocked")  
44 65
45 @admin_user = User.new(params[:user]) 66 @admin_user = User.new(params[:user])
46 @admin_user.admin = (admin && admin.to_i > 0) 67 @admin_user.admin = (admin && admin.to_i > 0)
47 - @admin_user.blocked = blocked  
48 68
49 respond_to do |format| 69 respond_to do |format|
50 if @admin_user.save 70 if @admin_user.save
@@ -59,7 +79,6 @@ class Admin::UsersController < ApplicationController @@ -59,7 +79,6 @@ class Admin::UsersController < ApplicationController
59 79
60 def update 80 def update
61 admin = params[:user].delete("admin") 81 admin = params[:user].delete("admin")
62 - blocked = params[:user].delete("blocked")  
63 82
64 if params[:user][:password].blank? 83 if params[:user][:password].blank?
65 params[:user].delete(:password) 84 params[:user].delete(:password)
@@ -68,7 +87,6 @@ class Admin::UsersController < ApplicationController @@ -68,7 +87,6 @@ class Admin::UsersController < ApplicationController
68 87
69 @admin_user = User.find(params[:id]) 88 @admin_user = User.find(params[:id])
70 @admin_user.admin = (admin && admin.to_i > 0) 89 @admin_user.admin = (admin && admin.to_i > 0)
71 - @admin_user.blocked = blocked  
72 90
73 respond_to do |format| 91 respond_to do |format|
74 if @admin_user.update_attributes(params[:user]) 92 if @admin_user.update_attributes(params[:user])
app/controllers/application_controller.rb
1 class ApplicationController < ActionController::Base 1 class ApplicationController < ActionController::Base
2 before_filter :authenticate_user! 2 before_filter :authenticate_user!
  3 + before_filter :reject_blocked!
3 before_filter :set_current_user_for_mailer 4 before_filter :set_current_user_for_mailer
4 protect_from_forgery 5 protect_from_forgery
5 helper_method :abilities, :can? 6 helper_method :abilities, :can?
@@ -16,6 +17,14 @@ class ApplicationController &lt; ActionController::Base @@ -16,6 +17,14 @@ class ApplicationController &lt; ActionController::Base
16 17
17 protected 18 protected
18 19
  20 + def reject_blocked!
  21 + if current_user && current_user.blocked
  22 + sign_out current_user
  23 + flash[:alert] = "Your account was blocked"
  24 + redirect_to new_user_session_path
  25 + end
  26 + end
  27 +
19 def after_sign_in_path_for resource 28 def after_sign_in_path_for resource
20 if resource.is_a?(User) && resource.respond_to?(:blocked) && resource.blocked 29 if resource.is_a?(User) && resource.respond_to?(:blocked) && resource.blocked
21 sign_out resource 30 sign_out resource
app/models/user.rb
@@ -48,7 +48,25 @@ class User &lt; ActiveRecord::Base @@ -48,7 +48,25 @@ class User &lt; ActiveRecord::Base
48 48
49 before_create :ensure_authentication_token 49 before_create :ensure_authentication_token
50 alias_attribute :private_token, :authentication_token 50 alias_attribute :private_token, :authentication_token
  51 +
51 scope :not_in_project, lambda { |project| where("id not in (:ids)", :ids => project.users.map(&:id) ) } 52 scope :not_in_project, lambda { |project| where("id not in (:ids)", :ids => project.users.map(&:id) ) }
  53 + scope :admins, where(:admin => true)
  54 + scope :blocked, where(:blocked => true)
  55 + scope :active, where(:blocked => false)
  56 +
  57 + def self.filter filter_name
  58 + case filter_name
  59 + when "admins"; self.admins
  60 + when "blocked"; self.blocked
  61 + when "wop"; self.without_projects
  62 + else
  63 + self.active
  64 + end
  65 + end
  66 +
  67 + def self.without_projects
  68 + where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)')
  69 + end
52 70
53 def identifier 71 def identifier
54 email.gsub /[@.]/, "_" 72 email.gsub /[@.]/, "_"
@@ -58,6 +76,7 @@ class User &lt; ActiveRecord::Base @@ -58,6 +76,7 @@ class User &lt; ActiveRecord::Base
58 admin 76 admin
59 end 77 end
60 78
  79 +
61 def require_ssh_key? 80 def require_ssh_key?
62 keys.count == 0 81 keys.count == 0
63 end 82 end
@@ -101,6 +120,17 @@ class User &lt; ActiveRecord::Base @@ -101,6 +120,17 @@ class User &lt; ActiveRecord::Base
101 def project_ids 120 def project_ids
102 projects.map(&:id) 121 projects.map(&:id)
103 end 122 end
  123 +
  124 + # Remove user from all projects and
  125 + # set blocked attribute to true
  126 + def block
  127 + users_projects.all.each do |membership|
  128 + return false unless membership.destroy
  129 + end
  130 +
  131 + self.blocked = true
  132 + save
  133 + end
104 end 134 end
105 # == Schema Information 135 # == Schema Information
106 # 136 #
app/views/admin/projects/index.html.haml
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 Projects 2 Projects
3 = link_to 'New Project', new_admin_project_path, :class => "btn small right" 3 = link_to 'New Project', new_admin_project_path, :class => "btn small right"
4 %br 4 %br
5 -%table.zebra-striped.table-bordered 5 +%table.admin-table
6 %thead 6 %thead
7 %th Name 7 %th Name
8 %th Path 8 %th Path
app/views/admin/projects/show.html.haml
@@ -2,9 +2,8 @@ @@ -2,9 +2,8 @@
2 = @admin_project.name 2 = @admin_project.name
3 = link_to 'Edit', edit_admin_project_path(@admin_project), :class => "btn right small" 3 = link_to 'Edit', edit_admin_project_path(@admin_project), :class => "btn right small"
4 4
5 -%hr  
6 -  
7 -%table.zebra-striped 5 +%br
  6 +%table.zebra-striped.table-bordered
8 %tr 7 %tr
9 %td 8 %td
10 %b 9 %b
@@ -29,47 +28,47 @@ @@ -29,47 +28,47 @@
29 Description: 28 Description:
30 %td 29 %td
31 = @admin_project.description 30 = @admin_project.description
  31 +%br
  32 +%h3
  33 + Team
  34 + %small
  35 + (#{@admin_project.users_projects.count})
  36 +%br
  37 +%table.zebra-striped.table-bordered
  38 + %thead
  39 + %tr
  40 + %th Name
  41 + %th Project Access
  42 + %th Repository Access
  43 + %th
32 44
  45 + - @admin_project.users_projects.each do |tm|
  46 + %tr
  47 + %td
  48 + = link_to tm.user_name, admin_user_path(tm.user)
  49 + %td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), :class => "medium project-access-select", :disabled => :disabled
  50 + %td= link_to 'Edit Access', edit_admin_team_member_path(tm), :class => "btn small"
  51 + %td= link_to 'Remove from team', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete, :class => "btn danger small"
33 52
34 -.span12  
35 -  
36 - %h3  
37 - Team  
38 - %small  
39 - (#{@admin_project.users_projects.count})  
40 -  
41 - %hr  
42 -  
43 - %table.zebra-striped 53 +%br
  54 +%h3 Add new team member
  55 +%br
  56 += form_tag team_update_admin_project_path(@admin_project), :class => "bulk_import", :method => :put do
  57 + %table.zebra-striped.table-bordered
44 %thead 58 %thead
45 %tr 59 %tr
46 - %th Name  
47 - %th Project Access  
48 - %th Repository Access  
49 - %th 60 + %th Users
  61 + %th Project Access:
50 62
51 - - @admin_project.users_projects.each do |tm|  
52 - %tr  
53 - %td  
54 - = link_to tm.user_name, admin_user_path(tm.user)  
55 - %td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), :class => "medium project-access-select", :disabled => :disabled  
56 - %td= link_to 'Edit Access', edit_admin_team_member_path(tm), :class => "btn small"  
57 - %td= link_to 'Remove from team', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete, :class => "btn danger small"  
58 -  
59 - = form_tag team_update_admin_project_path(@admin_project), :class => "bulk_import", :method => :put do  
60 - %table  
61 - %thead  
62 - %tr  
63 - %th Users  
64 - %th Project Access:  
65 - %th Repo Access:  
66 -  
67 - %tr  
68 - %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), :multiple => true  
69 - %td= select_tag :project_access, options_for_select(Project.access_options), :class => "project-access-select" 63 + %tr
  64 + %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), :multiple => true
  65 + %td= select_tag :project_access, options_for_select(Project.access_options), :class => "project-access-select"
70 66
71 - .actions  
72 - = submit_tag 'Add', :class => "btn primary" 67 + %tr
  68 + %td= submit_tag 'Add', :class => "btn primary"
  69 + %td
  70 + Read more about project permissions
  71 + %strong= link_to "here", help_permissions_path, :class => "vlink"
73 72
74 :css 73 :css
75 form select { 74 form select {
app/views/admin/users/_form.html.haml
@@ -6,41 +6,55 @@ @@ -6,41 +6,55 @@
6 - @admin_user.errors.full_messages.each do |msg| 6 - @admin_user.errors.full_messages.each do |msg|
7 %li= msg 7 %li= msg
8 8
9 - .clearfix  
10 - = f.label :name  
11 - .input= f.text_field :name  
12 - .clearfix  
13 - = f.label :email  
14 - .input= f.text_field :email  
15 - .clearfix  
16 - = f.label :password  
17 - .input= f.password_field :password  
18 - .clearfix  
19 - = f.label :password_confirmation  
20 - .input= f.password_field :password_confirmation 9 + .row
  10 + .span6
  11 + .clearfix
  12 + = f.label :name
  13 + .input
  14 + = f.text_field :name
  15 + %span.help-inline * requried
  16 + .clearfix
  17 + = f.label :email
  18 + .input
  19 + = f.text_field :email
  20 + %span.help-inline * requried
  21 + .clearfix
  22 + = f.label :password
  23 + .input= f.password_field :password
  24 + .clearfix
  25 + = f.label :password_confirmation
  26 + .input= f.password_field :password_confirmation
  27 + %hr
  28 + .clearfix
  29 + = f.label :skype
  30 + .input= f.text_field :skype
  31 + .clearfix
  32 + = f.label :linkedin
  33 + .input= f.text_field :linkedin
  34 + .clearfix
  35 + = f.label :twitter
  36 + .input= f.text_field :twitter
  37 + .span6
  38 + .clearfix
  39 + = f.label :projects_limit
  40 + .input= f.text_field :projects_limit, :class => "small_input"
21 41
22 - .clearfix  
23 - = f.label :projects_limit  
24 - .input= f.text_field :projects_limit, :class => "small_input"  
25 -  
26 - .clearfix  
27 - = f.label :skype  
28 - .input= f.text_field :skype  
29 - .clearfix  
30 - = f.label :linkedin  
31 - .input= f.text_field :linkedin  
32 - .clearfix  
33 - = f.label :twitter  
34 - .input= f.text_field :twitter  
35 - %hr  
36 - .clearfix  
37 - = f.label :admin do  
38 - = f.check_box :admin  
39 - %span Administrator  
40 - .clearfix  
41 - = f.label :blocked do  
42 - = f.check_box :blocked  
43 - %span Blocked 42 + .alert
  43 + .clearfix
  44 + %p Give user ability to manage application.
  45 + = f.label :admin, :class => "checkbox" do
  46 + = f.check_box :admin
  47 + %span Administrator
  48 + - unless @admin_user.new_record?
  49 + .alert.alert-error
  50 + - if @admin_user.blocked
  51 + %span
  52 + = link_to 'Unblock', unblock_admin_user_path(@admin_user), :method => :put, :class => "btn small"
  53 + This user is blocked and is not able to login GitLab
  54 + - else
  55 + %span
  56 + = link_to 'Block', block_admin_user_path(@admin_user), :confirm => 'USER WILL BE BLOCKED! Are you sure?', :method => :put, :class => "btn small danger"
  57 + Blocked user will removed from all projects &amp; will not be able to login to GitLab.
44 .actions 58 .actions
45 = f.submit 'Save', :class => "btn primary" 59 = f.submit 'Save', :class => "btn primary"
46 - if @admin_user.new_record? 60 - if @admin_user.new_record?
app/views/admin/users/index.html.haml
@@ -2,15 +2,29 @@ @@ -2,15 +2,29 @@
2 Users 2 Users
3 = link_to 'New User', new_admin_user_path, :class => "btn small right" 3 = link_to 'New User', new_admin_user_path, :class => "btn small right"
4 %br 4 %br
5 -%table.zebra-striped.table-bordered 5 +
  6 +%ul.nav.nav-pills
  7 + %li{:class => "#{'active' unless params[:filter]}"}
  8 + = link_to "Active", admin_users_path
  9 + %li{:class => "#{'active' if params[:filter] == "admins"}"}
  10 + = link_to admin_users_path(:filter => "admins") do
  11 + Admins
  12 + %li{:class => "#{'active' if params[:filter] == "blocked"}"}
  13 + = link_to admin_users_path(:filter => "blocked") do
  14 + Blocked
  15 + %li{:class => "#{'active' if params[:filter] == "wop"}"}
  16 + = link_to admin_users_path(:filter => "wop") do
  17 + Without projects
  18 +
  19 +%table.admin-table
6 %thead 20 %thead
7 %th Admin 21 %th Admin
8 %th Name 22 %th Name
9 %th Email 23 %th Email
10 %th Projects 24 %th Projects
  25 + %th Edit
11 %th Blocked 26 %th Blocked
12 %th 27 %th
13 - %th  
14 28
15 - @admin_users.each do |user| 29 - @admin_users.each do |user|
16 %tr 30 %tr
@@ -18,8 +32,12 @@ @@ -18,8 +32,12 @@
18 %td= link_to user.name, [:admin, user] 32 %td= link_to user.name, [:admin, user]
19 %td= user.email 33 %td= user.email
20 %td= user.users_projects.count 34 %td= user.users_projects.count
21 - %td= check_box_tag "blocked", 1, user.blocked, :disabled => :disabled  
22 %td= link_to 'Edit', edit_admin_user_path(user), :id => "edit_#{dom_id(user)}", :class => "btn small" 35 %td= link_to 'Edit', edit_admin_user_path(user), :id => "edit_#{dom_id(user)}", :class => "btn small"
23 - %td= link_to 'Destroy', [:admin, user], :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger" 36 + %td
  37 + - if user.blocked
  38 + = link_to 'Unblock', unblock_admin_user_path(user), :method => :put, :class => "btn small success"
  39 + - else
  40 + = link_to 'Block', block_admin_user_path(user), :confirm => 'USER WILL BE BLOCKED! Are you sure?', :method => :put, :class => "btn small danger"
  41 + %td= link_to 'Destroy', [:admin, user], :confirm => 'USER WILL BE REMOVED! Are you sure?', :method => :delete, :class => "btn small danger"
24 42
25 = paginate @admin_users, :theme => "admin" 43 = paginate @admin_users, :theme => "admin"
app/views/admin/users/show.html.haml
1 %h3 1 %h3
2 = @admin_user.name 2 = @admin_user.name
  3 + - if @admin_user.blocked
  4 + %small Blocked
  5 + - if @admin_user.admin
  6 + %small Administrator
3 = link_to 'Edit', edit_admin_user_path(@admin_user), :class => "btn small right" 7 = link_to 'Edit', edit_admin_user_path(@admin_user), :class => "btn small right"
4 8
5 -%hr 9 +%br
6 10
7 -%table.zebra-striped 11 +%table.zebra-striped.table-bordered
8 %tr 12 %tr
9 %td 13 %td
10 %b 14 %b
@@ -49,41 +53,47 @@ @@ -49,41 +53,47 @@
49 %td 53 %td
50 = @admin_user.twitter 54 = @admin_user.twitter
51 55
52 -%h3 Projects  
53 -%hr  
54 -  
55 -%table.zebra-striped  
56 - %tr  
57 - %thead  
58 - %th Name  
59 - %th Project Access  
60 - %th Repository Access  
61 - %th  
62 - %th  
63 -  
64 - - @admin_user.users_projects.each do |tm|  
65 - - project = tm.project  
66 - %tr  
67 - %td= link_to project.name, admin_project_path(project)  
68 - %td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), :class => "medium project-access-select", :disabled => :disabled  
69 - %td= link_to 'Edit Access', edit_admin_team_member_path(tm), :class => "btn small"  
70 - %td= link_to 'Remove from team', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger"  
71 56
  57 +%br
  58 +%h3 Add User to Projects
  59 +%br
72 = form_tag team_update_admin_user_path(@admin_user), :class => "bulk_import", :method => :put do 60 = form_tag team_update_admin_user_path(@admin_user), :class => "bulk_import", :method => :put do
73 - %table 61 + %table.table-bordered
74 %thead 62 %thead
75 %tr 63 %tr
76 %th Projects 64 %th Projects
77 %th Project Access: 65 %th Project Access:
78 - %th Repo Access:  
79 66
80 %tr 67 %tr
81 %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name), :multiple => true 68 %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name), :multiple => true
82 %td= select_tag :project_access, options_for_select(Project.access_options), :class => "project-access-select" 69 %td= select_tag :project_access, options_for_select(Project.access_options), :class => "project-access-select"
83 70
84 - .actions  
85 - = submit_tag 'Add', :class => "btn primary" 71 + %tr
  72 + %td= submit_tag 'Add', :class => "btn primary"
  73 + %td
  74 + Read more about project permissions
  75 + %strong= link_to "here", help_permissions_path, :class => "vlink"
  76 +%br
  77 +
  78 +- if @admin_user.projects.present?
  79 + %h3 Projects
  80 + %br
86 81
  82 + %table.zebra-striped.table-bordered
  83 + %tr
  84 + %thead
  85 + %th Name
  86 + %th Project Access
  87 + %th
  88 + %th
  89 +
  90 + - @admin_user.users_projects.each do |tm|
  91 + - project = tm.project
  92 + %tr
  93 + %td= link_to project.name, admin_project_path(project)
  94 + %td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), :class => "medium project-access-select", :disabled => :disabled
  95 + %td= link_to 'Edit Access', edit_admin_team_member_path(tm), :class => "btn small"
  96 + %td= link_to 'Remove from team', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger"
87 97
88 :css 98 :css
89 form select { 99 form select {
app/views/help/index.html.haml
1 %h3 1 %h3
2 Gitlabhq 2 Gitlabhq
3 - %span.right v2.3 3 + %span.right v2.4
4 %hr 4 %hr
5 %h4 Self Hosted Git Management 5 %h4 Self Hosted Git Management
6 %h4 Fast, secure and stable solution based on Ruby on Rails & Gitolite. 6 %h4 Fast, secure and stable solution based on Ruby on Rails & Gitolite.
app/views/layouts/admin.html.haml
@@ -7,8 +7,8 @@ @@ -7,8 +7,8 @@
7 .container 7 .container
8 %nav.main_menu 8 %nav.main_menu
9 = render "layouts/const_menu_links" 9 = render "layouts/const_menu_links"
10 - = link_to "Users", admin_users_path, :class => controller.controller_name == "users" ? "current" : nil  
11 = link_to "Projects", admin_projects_path, :class => controller.controller_name == "projects" ? "current" : nil 10 = link_to "Projects", admin_projects_path, :class => controller.controller_name == "projects" ? "current" : nil
  11 + = link_to "Users", admin_users_path, :class => controller.controller_name == "users" ? "current" : nil
12 = link_to "Emails", admin_emails_path, :class => controller.controller_name == "mailer" ? "current" : nil 12 = link_to "Emails", admin_emails_path, :class => controller.controller_name == "mailer" ? "current" : nil
13 = link_to "Resque", "/info/resque" 13 = link_to "Resque", "/info/resque"
14 14
config/routes.rb
@@ -14,6 +14,8 @@ Gitlab::Application.routes.draw do @@ -14,6 +14,8 @@ Gitlab::Application.routes.draw do
14 resources :users do 14 resources :users do
15 member do 15 member do
16 put :team_update 16 put :team_update
  17 + put :block
  18 + put :unblock
17 end 19 end
18 end 20 end
19 resources :projects, :constraints => { :id => /[^\/]+/ } do 21 resources :projects, :constraints => { :id => /[^\/]+/ } do