Commit f9988144 authored by Shinya Maeda's avatar Shinya Maeda

Merge branch 'user_permission_backend_streaming' into 'master'

User Permission export backend changes

See merge request gitlab-org/gitlab!51144
parents 5fe31be5 955d0fe0
...@@ -286,6 +286,14 @@ class ApplicationController < ActionController::Base ...@@ -286,6 +286,14 @@ class ApplicationController < ActionController::Base
end end
end end
def stream_csv_headers(csv_filename)
no_cache_headers
stream_headers
headers['Content-Type'] = 'text/csv; charset=utf-8; header=present'
headers['Content-Disposition'] = "attachment; filename=\"#{csv_filename}\""
end
def default_cache_control def default_cache_control
if request.xhr? if request.xhr?
ActionDispatch::Http::Cache::Response::DEFAULT_CACHE_CONTROL ActionDispatch::Http::Cache::Response::DEFAULT_CACHE_CONTROL
......
...@@ -12,11 +12,7 @@ class Admin::AuditLogReportsController < Admin::ApplicationController ...@@ -12,11 +12,7 @@ class Admin::AuditLogReportsController < Admin::ApplicationController
respond_to do |format| respond_to do |format|
format.csv do format.csv do
no_cache_headers stream_csv_headers(csv_filename)
stream_headers
headers['Content-Type'] = 'text/csv; charset=utf-8; header=present'
headers['Content-Disposition'] = "attachment; filename=\"#{csv_filename}\""
self.response_body = csv_data self.response_body = csv_data
end end
......
# frozen_string_literal: true
class Admin::UserPermissionExportsController < Admin::ApplicationController
feature_category :users
before_action :check_user_permission_export_availability!
def index
response = ::UserPermissions::ExportService.new(current_user).csv_data
respond_to do |format|
format.csv do
if response.success?
stream_csv_headers(csv_filename)
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
end
# frozen_string_literal: true # frozen_string_literal: true
module Members module UserPermissions
class PermissionsExportService class ExportService
def initialize(current_user) def initialize(current_user)
@current_user = current_user @current_user = current_user
end end
......
...@@ -24,6 +24,7 @@ namespace :admin do ...@@ -24,6 +24,7 @@ namespace :admin do
put :revoke put :revoke
end end
end end
resources :user_permission_exports, controller: 'user_permission_exports', only: [:index]
resource :license, only: [:show, :new, :create, :destroy] do resource :license, only: [:show, :new, :create, :destroy] do
get :download, on: :member get :download, on: :member
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Admin::UserPermissionExportsController do
let_it_be(:admin) { create(:admin) }
subject { get admin_user_permission_exports_path(format: :csv) }
before do
allow(admin).to receive(:can?).and_call_original
allow(admin).to receive(:can?).with(:export_user_permissions).and_return(authorized)
sign_in(admin)
end
describe '#index', :enable_admin_mode do
context 'when user is authorized' do
let(:authorized) { true }
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
alvina,alvina@test.com,Group,gitlab-org,Developer
jasper,jasper@test.com,Project,gitlab-org/www,Maintainer
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(export_csv_service).to have_received(:csv_data)
end
it 'has the appropriate data' do
subject
expect(csv_response).to eq([
%w(
Username
Email
Type
Path
Access
),
%w(
alvina
alvina@test.com
Group
gitlab-org
Developer
),
%w(
jasper
jasper@test.com
Project
gitlab-org/www
Maintainer
)
])
end
end
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
context 'when user is unauthorised' do
let(:authorized) { false }
it 'responds with :not_found' do
subject
expect(response).to have_gitlab_http_status(:not_found)
end
end
def csv_response
CSV.parse(response.body)
end
end
end
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Members::PermissionsExportService do RSpec.describe UserPermissions::ExportService do
let(:service) { described_class.new(current_user) } let(:service) { described_class.new(current_user) }
let_it_be(:admin) { create(:admin) } let_it_be(:admin) { create(:admin) }
......
...@@ -11823,6 +11823,9 @@ msgstr "" ...@@ -11823,6 +11823,9 @@ msgstr ""
msgid "Failed to find import label for Jira import." msgid "Failed to find import label for Jira import."
msgstr "" msgstr ""
msgid "Failed to generate report, please try again after sometime"
msgstr ""
msgid "Failed to get ref." msgid "Failed to get ref."
msgstr "" msgstr ""
......
...@@ -720,6 +720,49 @@ RSpec.describe ApplicationController do ...@@ -720,6 +720,49 @@ RSpec.describe ApplicationController do
end end
end end
describe '#stream_csv_headers' do
controller(described_class) do
def index
respond_to do |format|
format.csv do
stream_csv_headers('test.csv')
self.response_body = fixture_file_upload('spec/fixtures/csv_comma.csv')
end
end
end
end
subject { get :index, format: :csv }
before do
sign_in(user)
end
it 'sets no-cache headers', :aggregate_failures do
subject
expect(response.headers['Cache-Control']).to eq 'no-cache, no-store'
expect(response.headers['Pragma']).to eq 'no-cache'
expect(response.headers['Expires']).to eq 'Fri, 01 Jan 1990 00:00:00 GMT'
end
it 'sets stream headers', :aggregate_failures do
subject
expect(response.headers['Content-Length']).to be nil
expect(response.headers['X-Accel-Buffering']).to eq 'no'
expect(response.headers['Last-Modified']).to eq '0'
end
it 'sets the csv specific headers', :aggregate_failures do
subject
expect(response.headers['Content-Type']).to eq 'text/csv; charset=utf-8; header=present'
expect(response.headers['Content-Disposition']).to eq "attachment; filename=\"test.csv\""
end
end
context 'Gitlab::Session' do context 'Gitlab::Session' do
controller(described_class) do controller(described_class) do
prepend_before_action do prepend_before_action do
......
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