Commit 6feda25d authored by Gabriel Mazetto's avatar Gabriel Mazetto

Merge branch 'revert-a1b120e4' into 'master'

Revert "Merge branch '343859-admin-membership-export-background' into 'master'"

See merge request gitlab-org/gitlab!81527
parents e4c6d370 5bb5e1f7
......@@ -172,7 +172,6 @@ By default, impersonation is enabled. GitLab can be configured to [disable imper
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1772) in GitLab 13.8.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292436) in GitLab 13.9.
> - [Moved to delivery by email](https://gitlab.com/gitlab-org/gitlab/-/issues/343859) in GitLab 14.8.
An administrator can export user permissions for all users in the GitLab instance from the Admin Area's Users page.
The export lists direct membership the users have in groups and projects.
......@@ -190,11 +189,6 @@ Only the first 100,000 user accounts are exported.
![user permission export button](img/export_permissions_v13_11.png)
GitLab creates a CSV file and:
- In GitLab 14.7 and earlier, the file is downloaded in your browser.
- In GitLab 14.8 and later, the file is sent to your primary email address.
#### Users statistics
The **Users statistics** page provides an overview of user accounts by role. These statistics are
......
......@@ -6,15 +6,29 @@ class Admin::UserPermissionExportsController < Admin::ApplicationController
before_action :check_user_permission_export_availability!
def index
::Admin::MembershipsMailer.instance_memberships_export(requested_by: current_user).deliver_later
response = ::UserPermissions::ExportService.new(current_user).csv_data
flash[:success] = _('Report is generating and will be sent to your email address.')
respond_to do |format|
format.csv do
if response.success?
stream_csv_headers(csv_filename)
redirect_to admin_users_path
self.response_body = response.payload
else
flash[:alert] = _('Failed to generate report, please try again after sometime')
redirect_to admin_users_path
end
end
end
end
private
def csv_filename
"user-permissions-export-#{Time.current.to_i}.csv"
end
def check_user_permission_export_availability!
render_404 unless current_user.can?(:export_user_permissions)
end
......
# frozen_string_literal: true
class Admin::MembershipsMailer < ApplicationMailer
helper EmailsHelper
layout 'mailer'
def instance_memberships_export(requested_by:)
filename = "gitlab_memberships_#{Date.current.iso8601}.csv"
csv_data = UserPermissions::ExportService.new.execute.payload[:csv_data]
attachments[filename] = { content: csv_data, mime_type: 'text/csv' }
mail(
to: requested_by.notification_email_or_default,
subject: _('GitLab Memberships CSV Export')
)
end
end
......@@ -2,14 +2,26 @@
module UserPermissions
class ExportService
def execute
ServiceResponse.success(payload: { csv_data: csv_builder.render })
def initialize(current_user)
@current_user = current_user
end
def csv_data
return ServiceResponse.error(message: 'Insufficient permissions') unless allowed?
ServiceResponse.success(payload: csv_builder.render)
end
private
attr_reader :current_user
def allowed?
current_user.can?(:export_user_permissions)
end
def csv_builder
@csv_builder ||= CsvBuilder.new(data, header_to_value_hash)
@csv_builder ||= CsvBuilders::Stream.new(data, header_to_value_hash)
end
def data
......
%p{ style: 'font-size:18px; text-align:center; line-height:30px;' }
= _('The CSV export you requested of all user memberships is attached to this email.')
The CSV export you requested of all user memberships is attached to this email.
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Admin::MembershipsMailer do
include EmailSpec::Matchers
describe '.instance_memberships_export' do
let(:user) { create(:admin) }
subject { described_class.instance_memberships_export(requested_by: user) }
it 'contains memberships csv as an attachment' do
freeze_time do
expect(subject.attachments.size).to eq(1)
expect(subject.attachments[0].content_type).to eq('text/csv')
expect(subject.attachments[0].filename).to eq("gitlab_memberships_#{Date.current.iso8601}.csv")
end
end
it { is_expected.to have_subject 'GitLab Memberships CSV Export' }
it { is_expected.to deliver_to user.notification_email_or_default }
it { is_expected.to have_body_text('The CSV export you requested of all user memberships is attached to this email.') }
end
end
......@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Admin::UserPermissionExportsController do
let_it_be(:admin) { create(:admin) }
subject { get admin_user_permission_exports_path }
subject { get admin_user_permission_exports_path(format: :csv) }
before do
allow(admin).to receive(:can?).and_call_original
......@@ -14,18 +14,82 @@ RSpec.describe Admin::UserPermissionExportsController do
end
describe '#index', :enable_admin_mode do
context 'when authorized' do
context 'when user is authorized' do
let(:authorized) { true }
it 'redirects back to admin users list with notice' do
subject
before do
allow(UserPermissions::ExportService).to receive(:new).and_return(export_csv_service)
end
context 'when successful' do
let(:csv_data) do
<<~CSV
Username,Email,Type,Path,Access,Last Activity
alvina,alvina@test.com,Group,gitlab-org,Developer,2020-12-18
jasper,jasper@test.com,Project,gitlab-org/www,Maintainer,2020-12-16
CSV
end
let(:export_csv_service) do
instance_spy(UserPermissions::ExportService, csv_data: ServiceResponse.success(payload: csv_data))
end
it 'responds with :ok', :aggregate_failures do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(response.headers['Content-Type']).to eq('text/csv; charset=utf-8; header=present')
end
it 'invokes the Export Service' do
subject
expect(response).to redirect_to(admin_users_path)
expect(flash[:success]).to eq('Report is generating and will be sent to your email address.')
expect(export_csv_service).to have_received(:csv_data)
end
it 'has the appropriate data' do
subject
expect(csv_response).to eq([
[
'Username',
'Email',
'Type',
'Path',
'Access',
'Last Activity'
],
%w(
alvina
alvina@test.com
Group
gitlab-org
Developer
2020-12-18
),
%w(
jasper
jasper@test.com
Project
gitlab-org/www
Maintainer
2020-12-16
)
])
end
end
it 'enqueues a job to generate the CSV file' do
expect { subject }.to have_enqueued_mail(::Admin::MembershipsMailer, :instance_memberships_export)
context 'when Export fails' do
let(:export_csv_service) do
instance_spy(UserPermissions::ExportService, csv_data: ServiceResponse.error(message: 'Something went wrong!'))
end
it 'responds appropriately', :aggregate_failures do
subject
expect(flash[:alert]).to eq 'Failed to generate report, please try again after sometime'
expect(response).to redirect_to(admin_users_path)
end
end
end
......@@ -38,5 +102,9 @@ RSpec.describe Admin::UserPermissionExportsController do
expect(response).to have_gitlab_http_status(:not_found)
end
end
def csv_response
CSV.parse(response.body)
end
end
end
......@@ -3,13 +3,59 @@
require 'spec_helper'
RSpec.describe UserPermissions::ExportService do
let(:service) { described_class.new }
let(:service) { described_class.new(current_user) }
let_it_be(:admin) { create(:admin) }
let_it_be(:user) { create(:user, username: 'Jessica', email: 'jessica@test.com', last_activity_on: Date.new(2020, 12, 16)) }
context 'access' do
shared_examples 'allowed to export user permissions' do
it { expect(service.csv_data).to be_success }
end
shared_examples 'not allowed to export user permissions' do
it { expect(service.csv_data).not_to be_success }
end
before do
stub_licensed_features(export_user_permissions: licensed)
end
context 'when user is an admin', :enable_admin_mode do
let(:current_user) { admin }
context 'when licensed' do
let(:licensed) { true }
it_behaves_like 'allowed to export user permissions'
end
context 'when not licensed' do
let(:licensed) { false }
it_behaves_like 'not allowed to export user permissions'
end
end
context 'when user is not an admin' do
let(:current_user) { user }
context 'when licensed' do
let(:licensed) { true }
it_behaves_like 'not allowed to export user permissions'
end
context 'when not licensed' do
let(:licensed) { false }
it_behaves_like 'not allowed to export user permissions'
end
end
end
context 'data verification', :enable_admin_mode do
subject(:csv) { CSV.parse(service.execute.payload[:csv_data], headers: true) }
subject(:csv) { CSV.parse(service.csv_data.payload.to_a.join, headers: true) }
let_it_be(:current_user) { admin }
let_it_be(:group) { create(:group) }
......
......@@ -15056,6 +15056,9 @@ msgstr ""
msgid "Failed to generate export, please try again later."
msgstr ""
msgid "Failed to generate report, please try again after sometime"
msgstr ""
msgid "Failed to get ref."
msgstr ""
......@@ -16528,9 +16531,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
msgid "GitLab Memberships CSV Export"
msgstr ""
msgid "GitLab Pages"
msgstr ""
......@@ -30762,9 +30762,6 @@ msgstr ""
msgid "Report abuse to admin"
msgstr ""
msgid "Report is generating and will be sent to your email address."
msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
......@@ -36436,9 +36433,6 @@ msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
msgstr ""
msgid "The CSV export you requested of all user memberships is attached to this email."
msgstr ""
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
......
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