summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2015-06-23 14:24:16 +0000
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2015-06-23 14:24:16 +0000
commit94f130cbfc0349c1b17d4882e7d5c367030b21d1 (patch)
treea6c0258c256bece75fc5a5fcecc4fa2f74daed2a
parentb51fe6831123830f729295e16bd5aa99e3012c57 (diff)
parent4acd1f5d6a1942d4348b5d94e278fdb25c29e532 (diff)
downloadgitlab-ce-94f130cbfc0349c1b17d4882e7d5c367030b21d1.tar.gz
Merge branch 'admin-edit-identities' into 'master'
Admin can see, edit and remove user identities Related to #1415 and https://dev.gitlab.org/gitlab/gitlabhq/issues/2224 Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> See merge request !843
-rw-r--r--CHANGELOG1
-rw-r--r--app/controllers/admin/identities_controller.rb41
-rw-r--r--app/controllers/admin/users_controller.rb11
-rw-r--r--app/views/admin/identities/_form.html.haml19
-rw-r--r--app/views/admin/identities/_identity.html.haml12
-rw-r--r--app/views/admin/identities/edit.html.haml6
-rw-r--r--app/views/admin/identities/index.html.haml13
-rw-r--r--app/views/admin/users/_head.html.haml23
-rw-r--r--app/views/admin/users/groups.html.haml19
-rw-r--r--app/views/admin/users/keys.html.haml3
-rw-r--r--app/views/admin/users/projects.html.haml43
-rw-r--r--app/views/admin/users/show.html.haml386
-rw-r--r--config/routes.rb5
-rw-r--r--features/admin/users.feature20
-rw-r--r--features/steps/admin/users.rb41
-rw-r--r--lib/gitlab/o_auth/provider.rb19
16 files changed, 424 insertions, 238 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 43a4f0f2798..6ba09e952bf 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -10,6 +10,7 @@ v 7.13.0 (unreleased)
- Rename "Design" profile settings page to "Preferences".
- Allow users to customize their default Dashboard page.
- Update ssl_ciphers in Nginx example to remove DHE settings. This will deny forward secrecy for Android 2.3.7, Java 6 and OpenSSL 0.9.8
+ - Admin can edit and remove user identities
- Convert CRLF newlines to LF when committing using the web editor.
- API request /projects/:project_id/merge_requests?state=closed will return only closed merge requests without merged one. If you need ones that were merged - use state=merged.
- Allow Administrators to filter the user list by those with or without Two-factor Authentication enabled.
diff --git a/app/controllers/admin/identities_controller.rb b/app/controllers/admin/identities_controller.rb
new file mode 100644
index 00000000000..d28614731f9
--- /dev/null
+++ b/app/controllers/admin/identities_controller.rb
@@ -0,0 +1,41 @@
+class Admin::IdentitiesController < Admin::ApplicationController
+ before_action :user
+ before_action :identity, except: :index
+
+ def index
+ @identities = @user.identities
+ end
+
+ def edit
+ end
+
+ def update
+ if @identity.update_attributes(identity_params)
+ redirect_to admin_user_identities_path(@user), notice: 'User identity was successfully updated.'
+ else
+ render :edit
+ end
+ end
+
+ def destroy
+ if @identity.destroy
+ redirect_to admin_user_identities_path(@user), notice: 'User identity was successfully removed.'
+ else
+ redirect_to admin_user_identities_path(@user), alert: 'Failed to remove user identity.'
+ end
+ end
+
+ protected
+
+ def user
+ @user ||= User.find_by!(username: params[:user_id])
+ end
+
+ def identity
+ @identity ||= user.identities.find(params[:id])
+ end
+
+ def identity_params
+ params.require(:identity).permit(:provider, :extern_uid)
+ end
+end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 2bc236871b0..ec29c320654 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -1,5 +1,5 @@
class Admin::UsersController < Admin::ApplicationController
- before_action :user, only: [:show, :edit, :update, :destroy]
+ before_action :user, except: [:index, :new, :create]
def index
@users = User.order_name_asc.filter(params[:filter])
@@ -9,8 +9,17 @@ class Admin::UsersController < Admin::ApplicationController
end
def show
+ end
+
+ def projects
@personal_projects = user.personal_projects
@joined_projects = user.projects.joined(@user)
+ end
+
+ def groups
+ end
+
+ def keys
@keys = user.keys
end
diff --git a/app/views/admin/identities/_form.html.haml b/app/views/admin/identities/_form.html.haml
new file mode 100644
index 00000000000..b405aa6e8e3
--- /dev/null
+++ b/app/views/admin/identities/_form.html.haml
@@ -0,0 +1,19 @@
+= form_for [:admin, @user, @identity], html: { class: 'form-horizontal fieldset-form' } do |f|
+ - if @identity.errors.any?
+ #error_explanation
+ .alert.alert-danger
+ - @identity.errors.full_messages.each do |msg|
+ %p= msg
+
+ .form-group
+ = f.label :provider, class: 'control-label'
+ .col-sm-10
+ = f.select :provider, Gitlab::OAuth::Provider.names, { allow_blank: false }, class: 'form-control'
+ .form-group
+ = f.label :extern_uid, "Identifier", class: 'control-label'
+ .col-sm-10
+ = f.text_field :extern_uid, required: true, class: 'form-control', required: true
+
+ .form-actions
+ = f.submit 'Save changes', class: "btn btn-save"
+
diff --git a/app/views/admin/identities/_identity.html.haml b/app/views/admin/identities/_identity.html.haml
new file mode 100644
index 00000000000..671c4fbc677
--- /dev/null
+++ b/app/views/admin/identities/_identity.html.haml
@@ -0,0 +1,12 @@
+%tr
+ %td
+ = identity.provider
+ %td
+ = identity.extern_uid
+ %td
+ = link_to edit_admin_user_identity_path(@user, identity), class: 'btn btn-xs btn-grouped' do
+ Edit
+ = link_to [:admin, @user, identity], method: :delete,
+ class: 'btn btn-xs btn-danger',
+ data: { confirm: "Are you sure you want to remove this identity?" } do
+ Delete
diff --git a/app/views/admin/identities/edit.html.haml b/app/views/admin/identities/edit.html.haml
new file mode 100644
index 00000000000..515d46b0f29
--- /dev/null
+++ b/app/views/admin/identities/edit.html.haml
@@ -0,0 +1,6 @@
+- page_title "Edit", @identity.provider, "Identities", @user.name, "Users"
+%h3.page-title
+ Edit identity for #{@user.name}
+%hr
+
+= render 'form'
diff --git a/app/views/admin/identities/index.html.haml b/app/views/admin/identities/index.html.haml
new file mode 100644
index 00000000000..ae57e3adc4d
--- /dev/null
+++ b/app/views/admin/identities/index.html.haml
@@ -0,0 +1,13 @@
+- page_title "Identities", @user.name, "Users"
+= render 'admin/users/head'
+
+- if @identities.present?
+ %table.table
+ %thead
+ %tr
+ %th Provider
+ %th Identifier
+ %th
+ = render @identities
+- else
+ %h4 This user has no identities
diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml
new file mode 100644
index 00000000000..9d5e934c8ba
--- /dev/null
+++ b/app/views/admin/users/_head.html.haml
@@ -0,0 +1,23 @@
+%h3.page-title
+ = @user.name
+ - if @user.blocked?
+ %span.cred (Blocked)
+ - if @user.admin
+ %span.cred (Admin)
+
+ .pull-right
+ = link_to edit_admin_user_path(@user), class: "btn btn-grouped" do
+ %i.fa.fa-pencil-square-o
+ Edit
+%hr
+%ul.nav.nav-tabs
+ = nav_link(path: 'users#show') do
+ = link_to "Account", admin_user_path(@user)
+ = nav_link(path: 'users#groups') do
+ = link_to "Groups", groups_admin_user_path(@user)
+ = nav_link(path: 'users#projects') do
+ = link_to "Projects", projects_admin_user_path(@user)
+ = nav_link(path: 'users#keys') do
+ = link_to "SSH keys", keys_admin_user_path(@user)
+ = nav_link(controller: :identities) do
+ = link_to "Identities", admin_user_identities_path(@user)
diff --git a/app/views/admin/users/groups.html.haml b/app/views/admin/users/groups.html.haml
new file mode 100644
index 00000000000..dbecb7bbfd6
--- /dev/null
+++ b/app/views/admin/users/groups.html.haml
@@ -0,0 +1,19 @@
+- page_title "Groups", @user.name, "Users"
+= render 'admin/users/head'
+
+- if @user.group_members.present?
+ .panel.panel-default
+ .panel-heading Groups:
+ %ul.well-list
+ - @user.group_members.each do |group_member|
+ - group = group_member.group
+ %li.group_member
+ %span{class: ("list-item-name" unless group_member.owner?)}
+ %strong= link_to group.name, admin_group_path(group)
+ .pull-right
+ %span.light= group_member.human_access
+ - unless group_member.owner?
+ = link_to group_group_member_path(group, group_member), data: { confirm: remove_user_from_group_message(group, group_member) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from group' do
+ %i.fa.fa-times.fa-inverse
+- else
+ .nothing-here-block This user has no groups.
diff --git a/app/views/admin/users/keys.html.haml b/app/views/admin/users/keys.html.haml
new file mode 100644
index 00000000000..07110717082
--- /dev/null
+++ b/app/views/admin/users/keys.html.haml
@@ -0,0 +1,3 @@
+- page_title "Keys", @user.name, "Users"
+= render 'admin/users/head'
+= render 'profiles/keys/key_table', admin: true
diff --git a/app/views/admin/users/projects.html.haml b/app/views/admin/users/projects.html.haml
new file mode 100644
index 00000000000..0d7a1a25a80
--- /dev/null
+++ b/app/views/admin/users/projects.html.haml
@@ -0,0 +1,43 @@
+- page_title "Projects", @user.name, "Users"
+= render 'admin/users/head'
+
+- if @user.groups.any?
+ .panel.panel-default
+ .panel-heading Group projects
+ %ul.well-list
+ - @user.groups.each do |group|
+ %li
+ %strong= group.name
+ &ndash; access to
+ #{pluralize(group.projects.count, 'project')}
+
+.row
+ .col-md-6
+ - if @personal_projects.present?
+ = render 'users/projects', projects: @personal_projects
+ - else
+ .nothing-here-block This user has no personal projects.
+
+
+ .col-md-6
+ .panel.panel-default
+ .panel-heading Joined projects (#{@joined_projects.count})
+ %ul.well-list
+ - @joined_projects.sort_by(&:name_with_namespace).each do |project|
+ - member = project.team.find_member(@user.id)
+ %li.project_member
+ .list-item-name
+ = link_to admin_namespace_project_path(project.namespace, project), class: dom_class(project) do
+ = project.name_with_namespace
+
+ - if member
+ .pull-right
+ - if member.owner?
+ %span.light Owner
+ - else
+ %span.light= member.human_access
+
+ - if member.respond_to? :project
+ = link_to namespace_project_project_member_path(project.namespace, project, member), data: { confirm: remove_from_project_team_message(project, member) }, remote: true, method: :delete, class: "btn-xs btn btn-remove", title: 'Remove user from project' do
+ %i.fa.fa-times
+
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 48cd22fc34b..2662b3569ec 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -1,240 +1,154 @@
- page_title @user.name, "Users"
-%h3.page-title
- User:
- = @user.name
- - if @user.blocked?
- %span.cred (Blocked)
- - if @user.admin
- %span.cred (Admin)
-
- .pull-right
- = link_to edit_admin_user_path(@user), class: "btn btn-grouped" do
- %i.fa.fa-pencil-square-o
- Edit
-%hr
-%ul.nav.nav-tabs
- %li.active
- %a{"data-toggle" => "tab", href: "#account"} Account
- %li
- %a{"data-toggle" => "tab", href: "#profile"} Profile
- %li
- %a{"data-toggle" => "tab", href: "#groups"} Groups
- %li
- %a{"data-toggle" => "tab", href: "#projects"} Projects
- %li
- %a{"data-toggle" => "tab", href: "#ssh-keys"} SSH keys
-
-.tab-content
- #account.tab-pane.active
- .row
- .col-md-6
- .panel.panel-default
- .panel-heading
- Account:
- %ul.well-list
- %li
- %span.light Name:
- %strong= @user.name
- %li
- %span.light Username:
- %strong
- = @user.username
- %li
- %span.light Email:
- %strong
- = mail_to @user.email
- - @user.emails.each do |email|
- %li
- %span.light Secondary email:
- %strong= email.email
- = link_to remove_email_admin_user_path(@user, email), data: { confirm: "Are you sure you want to remove #{email.email}?" }, method: :delete, class: "btn-xs btn btn-remove pull-right", title: 'Remove secondary email', id: "remove_email_#{email.id}" do
- %i.fa.fa-times
-
- %li.two-factor-status
- %span.light Two-factor Authentication:
- %strong{class: @user.two_factor_enabled? ? 'cgreen' : 'cred'}
- - if @user.two_factor_enabled?
- Enabled
- - else
- Disabled
-
- %li
- %span.light Can create groups:
- %strong
- = @user.can_create_group ? "Yes" : "No"
- %li
- %span.light Personal projects limit:
- %strong
- = @user.projects_limit
- %li
- %span.light Member since:
- %strong
- = @user.created_at.stamp("Nov 12, 2031")
- - if @user.confirmed_at
- %li
- %span.light Confirmed at:
- %strong
- = @user.confirmed_at.stamp("Nov 12, 2031")
+= render 'admin/users/head'
+
+.row
+ .col-md-6
+ .panel.panel-default
+ .panel-heading
+ = @user.name
+ %ul.well-list
+ %li
+ = image_tag avatar_icon(@user.email, 60), class: "avatar s60"
+ %li
+ %span.light Profile page:
+ %strong
+ = link_to user_path(@user) do
+ = @user.username
+ = render 'users/profile', user: @user
+
+ .panel.panel-default
+ .panel-heading
+ Account:
+ %ul.well-list
+ %li
+ %span.light Name:
+ %strong= @user.name
+ %li
+ %span.light Username:
+ %strong
+ = @user.username
+ %li
+ %span.light Email:
+ %strong
+ = mail_to @user.email
+ - @user.emails.each do |email|
+ %li
+ %span.light Secondary email:
+ %strong= email.email
+ = link_to remove_email_admin_user_path(@user, email), data: { confirm: "Are you sure you want to remove #{email.email}?" }, method: :delete, class: "btn-xs btn btn-remove pull-right", title: 'Remove secondary email', id: "remove_email_#{email.id}" do
+ %i.fa.fa-times
+
+ %li.two-factor-status
+ %span.light Two-factor Authentication:
+ %strong{class: @user.two_factor_enabled? ? 'cgreen' : 'cred'}
+ - if @user.two_factor_enabled?
+ Enabled
- else
- %li
- %span.light Confirmed:
- %strong.cred
- No
-
- %li
- %span.light Current sign-in at:
- %strong
- - if @user.current_sign_in_at
- = @user.current_sign_in_at.stamp("Nov 12, 2031")
- - else
- never
-
- %li
- %span.light Last sign-in at:
- %strong
- - if @user.last_sign_in_at
- = @user.last_sign_in_at.stamp("Nov 12, 2031")
- - else
- never
-
- %li
- %span.light Sign-in count:
- %strong
- = @user.sign_in_count
-
- - if @user.ldap_user?
- %li
- %span.light LDAP uid:
- %strong
- = @user.ldap_identity.extern_uid
-
- - if @user.created_by
- %li
- %span.light Created by:
- %strong
- = link_to @user.created_by.name, [:admin, @user.created_by]
-
- .col-md-6
- - unless @user == current_user
- - if @user.blocked?
- .panel.panel-info
- .panel-heading
- This user is blocked
- .panel-body
- %p Blocking user has the following effects:
- %ul
- %li User will not be able to login
- %li User will not be able to access git repositories
- %li Personal projects will be left
- %li Owned groups will be left
- %br
- = link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?' }
- - else
- .panel.panel-warning
- .panel-heading
- Block this user
- .panel-body
- %p Blocking user has the following effects:
- %ul
- %li User will not be able to login
- %li User will not be able to access git repositories
- %li User will be removed from joined projects and groups
- %li Personal projects will be left
- %li Owned groups will be left
- %br
- = link_to 'Block user', block_admin_user_path(@user), data: { confirm: 'USER WILL BE BLOCKED! Are you sure?' }, method: :put, class: "btn btn-warning"
-
- .panel.panel-danger
- .panel-heading
- Remove user
- .panel-body
- - if @user.can_be_removed?
- %p Deleting a user has the following effects:
- %ul
- %li All user content like authored issues, snippets, comments will be removed
- - rp = @user.personal_projects.count
- - unless rp.zero?
- %li #{pluralize rp, 'personal project'} will be removed and cannot be restored
- %br
- = link_to 'Remove user', [:admin, @user], data: { confirm: "USER #{@user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "btn btn-remove"
- - else
- - if @user.solo_owned_groups.present?
- %p
- This user is currently an owner in these groups:
- %strong #{@user.solo_owned_groups.map(&:name).join(', ')}
- %p
- You must transfer ownership or delete these groups before you can delete this user.
+ Disabled
+
+ %li
+ %span.light Can create groups:
+ %strong
+ = @user.can_create_group ? "Yes" : "No"
+ %li
+ %span.light Personal projects limit:
+ %strong
+ = @user.projects_limit
+ %li
+ %span.light Member since:
+ %strong
+ = @user.created_at.stamp("Nov 12, 2031")
+ - if @user.confirmed_at
+ %li
+ %span.light Confirmed at:
+ %strong
+ = @user.confirmed_at.stamp("Nov 12, 2031")
+ - else
+ %li
+ %span.light Confirmed:
+ %strong.cred
+ No
+
+ %li
+ %span.light Current sign-in at:
+ %strong
+ - if @user.current_sign_in_at
+ = @user.current_sign_in_at.stamp("Nov 12, 2031")
+ - else
+ never
- #profile.tab-pane
- .row
- .col-md-6
- .panel.panel-default
+ %li
+ %span.light Last sign-in at:
+ %strong
+ - if @user.last_sign_in_at
+ = @user.last_sign_in_at.stamp("Nov 12, 2031")
+ - else
+ never
+
+ %li
+ %span.light Sign-in count:
+ %strong
+ = @user.sign_in_count
+
+ - if @user.ldap_user?
+ %li
+ %span.light LDAP uid:
+ %strong
+ = @user.ldap_identity.extern_uid
+
+ - if @user.created_by
+ %li
+ %span.light Created by:
+ %strong
+ = link_to @user.created_by.name, [:admin, @user.created_by]
+
+ .col-md-6
+ - unless @user == current_user
+ - if @user.blocked?
+ .panel.panel-info
.panel-heading
- = @user.name
- %ul.well-list
- %li
- = image_tag avatar_icon(@user.email, 60), class: "avatar s60"
- %li
- %span.light Profile page:
- %strong
- = link_to user_path(@user) do
- = @user.username
- .col-md-6
- = render 'users/profile', user: @user
-
- #groups.tab-pane
- - if @user.group_members.present?
- .panel.panel-default
- .panel-heading Groups:
- %ul.well-list
- - @user.group_members.each do |group_member|
- - group = group_member.group
- %li.group_member
- %span{class: ("list-item-name" unless group_member.owner?)}
- %strong= link_to group.name, admin_group_path(group)
- .pull-right
- %span.light= group_member.human_access
- - unless group_member.owner?
- = link_to group_group_member_path(group, group_member), data: { confirm: remove_user_from_group_message(group, group_member) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from group' do
- %i.fa.fa-times.fa-inverse
- - else
- .nothing-here-block This user has no groups.
-
- #projects.tab-pane
- - if @user.groups.any?
- .panel.panel-default
- .panel-heading Group projects
- %ul.well-list
- - @user.groups.each do |group|
- %li
- %strong= group.name
- &ndash; access to
- #{pluralize(group.projects.count, 'project')}
-
- .row
- .col-md-6
- = render 'users/projects', projects: @personal_projects
-
- .col-md-6
- .panel.panel-default
- .panel-heading Joined projects (#{@joined_projects.count})
- %ul.well-list
- - @joined_projects.sort_by(&:name_with_namespace).each do |project|
- - member = project.team.find_member(@user.id)
- %li.project_member
- .list-item-name
- = link_to admin_namespace_project_path(project.namespace, project), class: dom_class(project) do
- = project.name_with_namespace
-
- - if member
- .pull-right
- - if member.owner?
- %span.light Owner
- - else
- %span.light= member.human_access
-
- - if member.respond_to? :project
- = link_to namespace_project_project_member_path(project.namespace, project, member), data: { confirm: remove_from_project_team_message(project, member) }, remote: true, method: :delete, class: "btn-xs btn btn-remove", title: 'Remove user from project' do
- %i.fa.fa-times
- #ssh-keys.tab-pane
- = render 'profiles/keys/key_table', admin: true
+ This user is blocked
+ .panel-body
+ %p Blocking user has the following effects:
+ %ul
+ %li User will not be able to login
+ %li User will not be able to access git repositories
+ %li Personal projects will be left
+ %li Owned groups will be left
+ %br
+ = link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?' }
+ - else
+ .panel.panel-warning
+ .panel-heading
+ Block this user
+ .panel-body
+ %p Blocking user has the following effects:
+ %ul
+ %li User will not be able to login
+ %li User will not be able to access git repositories
+ %li User will be removed from joined projects and groups
+ %li Personal projects will be left
+ %li Owned groups will be left
+ %br
+ = link_to 'Block user', block_admin_user_path(@user), data: { confirm: 'USER WILL BE BLOCKED! Are you sure?' }, method: :put, class: "btn btn-warning"
+
+ .panel.panel-danger
+ .panel-heading
+ Remove user
+ .panel-body
+ - if @user.can_be_removed?
+ %p Deleting a user has the following effects:
+ %ul
+ %li All user content like authored issues, snippets, comments will be removed
+ - rp = @user.personal_projects.count
+ - unless rp.zero?
+ %li #{pluralize rp, 'personal project'} will be removed and cannot be restored
+ %br
+ = link_to 'Remove user', [:admin, @user], data: { confirm: "USER #{@user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "btn btn-remove"
+ - else
+ - if @user.solo_owned_groups.present?
+ %p
+ This user is currently an owner in these groups:
+ %strong #{@user.solo_owned_groups.map(&:name).join(', ')}
+ %p
+ You must transfer ownership or delete these groups before you can delete this user.
diff --git a/config/routes.rb b/config/routes.rb
index d60bc796fdb..33f55dde476 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -149,7 +149,12 @@ Gitlab::Application.routes.draw do
namespace :admin do
resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do
resources :keys, only: [:show, :destroy]
+ resources :identities, only: [:index, :edit, :update, :destroy]
+
member do
+ get :projects
+ get :keys
+ get :groups
put :team_update
put :block
put :unblock
diff --git a/features/admin/users.feature b/features/admin/users.feature
index 1a8720dd77e..6755645778a 100644
--- a/features/admin/users.feature
+++ b/features/admin/users.feature
@@ -28,7 +28,7 @@ Feature: Admin Users
When I submit modified user
Then I see user attributes changed
-@javascript
+ @javascript
Scenario: Remove users secondary email
Given I visit admin users page
And I view the user with secondary email
@@ -40,8 +40,26 @@ Feature: Admin Users
Given user "Pete" with ssh keys
And I visit admin users page
And click on user "Pete"
+ And click on ssh keys tab
Then I should see key list
And I click on the key title
Then I should see key details
And I click on remove key
Then I should see the key removed
+
+ Scenario: Show user identities
+ Given user "Pete" with twitter account
+ And I visit "Pete" identities page in admin
+ Then I should see twitter details
+
+ Scenario: Update user identities
+ Given user "Pete" with twitter account
+ And I visit "Pete" identities page in admin
+ And I modify twitter identity
+ Then I should see twitter details updated
+
+ Scenario: Remove user identities
+ Given user "Pete" with twitter account
+ And I visit "Pete" identities page in admin
+ And I remove twitter identity
+ Then I should not see twitter details
diff --git a/features/steps/admin/users.rb b/features/steps/admin/users.rb
index 34a3ed9f615..6c4b91586d6 100644
--- a/features/steps/admin/users.rb
+++ b/features/steps/admin/users.rb
@@ -114,4 +114,45 @@ class Spinach::Features::AdminUsers < Spinach::FeatureSteps
step 'I should see the key removed' do
expect(page).not_to have_content 'ssh-rsa Key2'
end
+
+ step 'user "Pete" with twitter account' do
+ @user = create(:user, name: 'Pete')
+ @user.identities.create!(extern_uid: '123456', provider: 'twitter')
+ end
+
+ step 'I visit "Pete" identities page in admin' do
+ allow(Gitlab::OAuth::Provider).to receive(:names).and_return(%w(twitter twitter_updated))
+ visit admin_user_identities_path(@user)
+ end
+
+ step 'I should see twitter details' do
+ expect(page).to have_content 'Pete'
+ expect(page).to have_content 'twitter'
+ end
+
+ step 'I modify twitter identity' do
+ find('.table').find(:link, 'Edit').click
+ fill_in 'identity_extern_uid', with: '654321'
+ select 'twitter_updated', from: 'identity_provider'
+ click_button 'Save changes'
+ end
+
+ step 'I should see twitter details updated' do
+ expect(page).to have_content 'Pete'
+ expect(page).to have_content 'twitter_updated'
+ expect(page).to have_content '654321'
+ end
+
+ step 'I remove twitter identity' do
+ click_link 'Delete'
+ end
+
+ step 'I should not see twitter details' do
+ expect(page).to have_content 'Pete'
+ expect(page).to_not have_content 'twitter'
+ end
+
+ step 'click on ssh keys tab' do
+ click_link 'SSH keys'
+ end
end
diff --git a/lib/gitlab/o_auth/provider.rb b/lib/gitlab/o_auth/provider.rb
new file mode 100644
index 00000000000..f986499a27c
--- /dev/null
+++ b/lib/gitlab/o_auth/provider.rb
@@ -0,0 +1,19 @@
+module Gitlab
+ module OAuth
+ class Provider
+ def self.names
+ providers = []
+
+ Gitlab.config.ldap.servers.values.each do |server|
+ providers << server['provider_name']
+ end
+
+ Gitlab.config.omniauth.providers.each do |provider|
+ providers << provider['name']
+ end
+
+ providers
+ end
+ end
+ end
+end