Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
839dad17a1
commit
8491ed6450
11 changed files with 342 additions and 2 deletions
56
app/helpers/admin/user_actions_helper.rb
Normal file
56
app/helpers/admin/user_actions_helper.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
module UserActionsHelper
|
||||
def admin_actions(user)
|
||||
return [] if user.internal?
|
||||
|
||||
@actions ||= ['edit']
|
||||
|
||||
return @actions if user == current_user
|
||||
|
||||
@user ||= user
|
||||
|
||||
blocked_actions
|
||||
deactivate_actions
|
||||
unlock_actions
|
||||
delete_actions
|
||||
|
||||
@actions
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def blocked_actions
|
||||
if @user.ldap_blocked?
|
||||
@actions << 'ldap'
|
||||
elsif @user.blocked? && @user.blocked_pending_approval?
|
||||
@actions << 'approve'
|
||||
@actions << 'reject'
|
||||
elsif @user.blocked?
|
||||
@actions << 'unblock'
|
||||
else
|
||||
@actions << 'block'
|
||||
end
|
||||
end
|
||||
|
||||
def deactivate_actions
|
||||
if @user.can_be_deactivated?
|
||||
@actions << 'deactivate'
|
||||
elsif @user.deactivated?
|
||||
@actions << 'activate'
|
||||
end
|
||||
end
|
||||
|
||||
def unlock_actions
|
||||
@actions << 'unlock' if @user.access_locked?
|
||||
end
|
||||
|
||||
def delete_actions
|
||||
return unless can?(current_user, :destroy_user, @user) && !@user.blocked_pending_approval? && @user.can_be_removed?
|
||||
|
||||
@actions << 'delete'
|
||||
@actions << 'delete_with_contributions'
|
||||
end
|
||||
end
|
||||
end
|
31
app/serializers/admin/user_entity.rb
Normal file
31
app/serializers/admin/user_entity.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class UserEntity < API::Entities::UserSafe
|
||||
include RequestAwareEntity
|
||||
include UsersHelper
|
||||
include UserActionsHelper
|
||||
|
||||
expose :created_at
|
||||
expose :email
|
||||
expose :last_activity_on
|
||||
expose :avatar_url
|
||||
expose :badges do |user|
|
||||
user_badges_in_admin_section(user)
|
||||
end
|
||||
|
||||
expose :projects_count do |user|
|
||||
user.authorized_projects.length
|
||||
end
|
||||
|
||||
expose :actions do |user|
|
||||
admin_actions(user)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_user
|
||||
options[:current_user]
|
||||
end
|
||||
end
|
||||
end
|
7
app/serializers/admin/user_serializer.rb
Normal file
7
app/serializers/admin/user_serializer.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class UserSerializer < BaseSerializer
|
||||
entity UserEntity
|
||||
end
|
||||
end
|
5
changelogs/unreleased/285103-serialize-admin-users.yml
Normal file
5
changelogs/unreleased/285103-serialize-admin-users.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add admin users serializer and entity
|
||||
merge_request: 48791
|
||||
author:
|
||||
type: added
|
|
@ -114,6 +114,7 @@ See the section on [ETag mismatch errors](#etag-mismatch) for more details.
|
|||
gitlab_rails['object_store']['objects']['packages']['bucket'] = '<packages>'
|
||||
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = '<dependency-proxy>'
|
||||
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = '<terraform-state>'
|
||||
gitlab_rails['object_store']['objects']['pages']['bucket'] = '<pages>'
|
||||
```
|
||||
|
||||
For GitLab 9.4 or later, if you're using AWS IAM profiles, be sure to omit the
|
||||
|
@ -160,6 +161,8 @@ See the section on [ETag mismatch errors](#etag-mismatch) for more details.
|
|||
bucket: <dependency_proxy>
|
||||
terraform_state:
|
||||
bucket: <terraform>
|
||||
pages:
|
||||
bucket: <pages>
|
||||
```
|
||||
|
||||
1. Edit `/home/git/gitlab-workhorse/config.toml` and add or amend the following lines:
|
||||
|
@ -440,6 +443,8 @@ required parameter within each type:
|
|||
bucket: dependency_proxy
|
||||
terraform_state:
|
||||
bucket: terraform
|
||||
pages:
|
||||
bucket: pages
|
||||
```
|
||||
|
||||
This maps to this Omnibus GitLab configuration:
|
||||
|
@ -454,6 +459,7 @@ gitlab_rails['object_store']['objects']['packages']['bucket'] = 'packages'
|
|||
gitlab_rails['object_store']['objects']['dependency_proxy']['enabled'] = false
|
||||
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = 'dependency-proxy'
|
||||
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = 'terraform-state'
|
||||
gitlab_rails['object_store']['objects']['pages']['bucket'] = 'pages'
|
||||
```
|
||||
|
||||
This is the list of valid `objects` that can be used:
|
||||
|
@ -467,6 +473,7 @@ This is the list of valid `objects` that can be used:
|
|||
| `packages` | [Project packages (e.g. PyPI, Maven, NuGet, etc.)](packages/index.md) |
|
||||
| `dependency_proxy` | [GitLab Dependency Proxy](packages/dependency_proxy.md) |
|
||||
| `terraform_state` | [Terraform state files](terraform_state.md) |
|
||||
| `pages` | [GitLab Pages](pages/index.md) |
|
||||
|
||||
Within each object type, three parameters can be defined:
|
||||
|
||||
|
@ -548,6 +555,7 @@ supported by consolidated configuration form, refer to the following guides:
|
|||
| [Pseudonymizer](pseudonymizer.md#configuration) (optional feature) **(ULTIMATE ONLY)** | No |
|
||||
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
|
||||
| [Terraform state files](terraform_state.md#using-object-storage) | Yes |
|
||||
| [GitLab Pages content](pages/index.md#using-object-storage) | Yes |
|
||||
|
||||
### Other alternatives to filesystem storage
|
||||
|
||||
|
|
|
@ -700,6 +700,77 @@ gitlab_pages['domain_config_source'] = nil
|
|||
For other common issues, see the [troubleshooting section](#failed-to-connect-to-the-internal-gitlab-api)
|
||||
or report an issue.
|
||||
|
||||
## Using object storage
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5577) in GitLab 13.6.
|
||||
|
||||
[Read more about using object storage with GitLab](../object_storage.md).
|
||||
|
||||
### Object storage settings
|
||||
|
||||
The following settings are:
|
||||
|
||||
- Nested under `pages:` and then `object_store:` on source installations.
|
||||
- Prefixed by `pages_object_store_` on Omnibus GitLab installations.
|
||||
|
||||
| Setting | Description | Default |
|
||||
|---------|-------------|---------|
|
||||
| `enabled` | Whether object storage is enabled. | `false` |
|
||||
| `remote_directory` | The name of the bucket where Pages site content is stored. | |
|
||||
| `connection` | Various connection options described below. | |
|
||||
|
||||
#### S3-compatible connection settings
|
||||
|
||||
See [the available connection settings for different providers](../object_storage.md#connection-settings).
|
||||
|
||||
In Omnibus installations:
|
||||
|
||||
1. Add the following lines to `/etc/gitlab/gitlab.rb` and replace the values with the ones you want:
|
||||
|
||||
```ruby
|
||||
gitlab_rails['pages_object_store_enabled'] = true
|
||||
gitlab_rails['pages_object_store_remote_directory'] = "pages"
|
||||
gitlab_rails['pages_object_store_connection'] = {
|
||||
'provider' => 'AWS',
|
||||
'region' => 'eu-central-1',
|
||||
'aws_access_key_id' => 'AWS_ACCESS_KEY_ID',
|
||||
'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY'
|
||||
}
|
||||
```
|
||||
|
||||
If you use AWS IAM profiles, be sure to omit the AWS access key and secret access key/value
|
||||
pairs:
|
||||
|
||||
```ruby
|
||||
gitlab_rails['pages_object_store_connection'] = {
|
||||
'provider' => 'AWS',
|
||||
'region' => 'eu-central-1',
|
||||
'use_iam_profile' => true
|
||||
}
|
||||
```
|
||||
|
||||
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure)
|
||||
for the changes to take effect.
|
||||
|
||||
In installations from source:
|
||||
|
||||
1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
|
||||
|
||||
```yaml
|
||||
pages:
|
||||
object_store:
|
||||
enabled: true
|
||||
remote_directory: "pages" # The bucket name
|
||||
connection:
|
||||
provider: AWS # Only AWS supported at the moment
|
||||
aws_access_key_id: AWS_ACESS_KEY_ID
|
||||
aws_secret_access_key: AWS_SECRET_ACCESS_KEY
|
||||
region: eu-central-1
|
||||
```
|
||||
|
||||
1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source)
|
||||
for the changes to take effect.
|
||||
|
||||
## Backup
|
||||
|
||||
GitLab Pages are part of the [regular backup](../../raketasks/backup_restore.md), so there is no separate backup to configure.
|
||||
|
|
|
@ -13,7 +13,7 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
|
|||
Each table below documents a GraphQL type. Types match loosely to models, but not all
|
||||
fields and methods on a model are available via GraphQL.
|
||||
|
||||
CAUTION: **Caution:**
|
||||
WARNING:
|
||||
Fields that are deprecated are marked with **{warning-solid}**.
|
||||
Items (fields, enums, etc) that have been removed according to our [deprecation process](../index.md#deprecation-process) can be found
|
||||
in [Removed Items](../removed_items.md).
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
Each table below documents a GraphQL type. Types match loosely to models, but not all
|
||||
fields and methods on a model are available via GraphQL.
|
||||
|
||||
CAUTION: **Caution:**
|
||||
WARNING:
|
||||
Fields that are deprecated are marked with **{warning-solid}**.
|
||||
Items (fields, enums, etc) that have been removed according to our [deprecation process](../index.md#deprecation-process) can be found
|
||||
in [Removed Items](../removed_items.md).
|
||||
|
|
105
spec/helpers/admin/user_actions_helper_spec.rb
Normal file
105
spec/helpers/admin/user_actions_helper_spec.rb
Normal file
|
@ -0,0 +1,105 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe Admin::UserActionsHelper do
|
||||
describe '#admin_actions' do
|
||||
let_it_be(:current_user) { build(:user) }
|
||||
|
||||
subject { helper.admin_actions(user) }
|
||||
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(current_user)
|
||||
allow(helper).to receive(:can?).with(current_user, :destroy_user, user).and_return(true)
|
||||
end
|
||||
|
||||
context 'the user is a bot' do
|
||||
let_it_be(:user) { build(:user, :bot) }
|
||||
|
||||
it { is_expected.to be_empty }
|
||||
end
|
||||
|
||||
context 'the current user and user are the same' do
|
||||
let_it_be(:user) { build(:user) }
|
||||
let_it_be(:current_user) { user }
|
||||
|
||||
it { is_expected.to contain_exactly("edit") }
|
||||
end
|
||||
|
||||
context 'the user is a standard user' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
it { is_expected.to contain_exactly("edit", "block", "deactivate", "delete", "delete_with_contributions") }
|
||||
end
|
||||
|
||||
context 'the user is an admin user' do
|
||||
let_it_be(:user) { create(:user, :admin) }
|
||||
|
||||
it { is_expected.to contain_exactly("edit", "block", "deactivate", "delete", "delete_with_contributions") }
|
||||
end
|
||||
|
||||
context 'the user is blocked by LDAP' do
|
||||
let_it_be(:user) { create(:omniauth_user, :ldap_blocked) }
|
||||
|
||||
it { is_expected.to contain_exactly("edit", "ldap", "delete", "delete_with_contributions") }
|
||||
end
|
||||
|
||||
context 'the user is blocked pending approval' do
|
||||
let_it_be(:user) { create(:user, :blocked_pending_approval) }
|
||||
|
||||
it { is_expected.to contain_exactly("edit", "approve", "reject") }
|
||||
end
|
||||
|
||||
context 'the user is blocked' do
|
||||
let_it_be(:user) { create(:user, :blocked) }
|
||||
|
||||
it { is_expected.to contain_exactly("edit", "unblock", "delete", "delete_with_contributions") }
|
||||
end
|
||||
|
||||
context 'the user is deactivated' do
|
||||
let_it_be(:user) { create(:user, :deactivated) }
|
||||
|
||||
it { is_expected.to contain_exactly("edit", "block", "activate", "delete", "delete_with_contributions") }
|
||||
end
|
||||
|
||||
context 'the user is locked' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
user.lock_access!
|
||||
end
|
||||
|
||||
it {
|
||||
is_expected.to contain_exactly(
|
||||
"edit",
|
||||
"block",
|
||||
"deactivate",
|
||||
"unlock",
|
||||
"delete",
|
||||
"delete_with_contributions"
|
||||
)
|
||||
}
|
||||
end
|
||||
|
||||
context 'the current_user does not have permission to delete the user' do
|
||||
let_it_be(:user) { build(:user) }
|
||||
|
||||
before do
|
||||
allow(helper).to receive(:can?).with(current_user, :destroy_user, user).and_return(false)
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly("edit", "block", "deactivate") }
|
||||
end
|
||||
|
||||
context 'the user is a sole owner of a group' do
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
group.add_owner(user)
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly("edit", "block", "deactivate") }
|
||||
end
|
||||
end
|
||||
end
|
31
spec/serializers/admin/user_entity_spec.rb
Normal file
31
spec/serializers/admin/user_entity_spec.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe Admin::UserEntity do
|
||||
let_it_be(:user) { build_stubbed(:user) }
|
||||
let(:request) { double('request') }
|
||||
|
||||
let(:entity) do
|
||||
described_class.new(user, request: request)
|
||||
end
|
||||
|
||||
describe '#as_json' do
|
||||
subject { entity.as_json&.keys }
|
||||
|
||||
it 'exposes correct attributes' do
|
||||
is_expected.to contain_exactly(
|
||||
:id,
|
||||
:name,
|
||||
:created_at,
|
||||
:email,
|
||||
:username,
|
||||
:last_activity_on,
|
||||
:avatar_url,
|
||||
:badges,
|
||||
:projects_count,
|
||||
:actions
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
26
spec/serializers/admin/user_serializer_spec.rb
Normal file
26
spec/serializers/admin/user_serializer_spec.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe Admin::UserSerializer do
|
||||
let(:resource) { build(:user) }
|
||||
|
||||
subject { described_class.new.represent(resource).keys }
|
||||
|
||||
context 'when there is a single object provided' do
|
||||
it 'contains important elements for the admin user table' do
|
||||
is_expected.to contain_exactly(
|
||||
:id,
|
||||
:name,
|
||||
:created_at,
|
||||
:email,
|
||||
:username,
|
||||
:last_activity_on,
|
||||
:avatar_url,
|
||||
:badges,
|
||||
:projects_count,
|
||||
:actions
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue