Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

APPEALS-64051 CSRF Updates #23467

Open
wants to merge 3 commits into
base: feature/APPEALS-47217
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions app/controllers/concerns/prodtest_only_concern.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

module ProdtestOnlyConcern
extend ActiveSupport::Concern

included do
before_action :prodtest_only
end

# Only accessible from prod-test environment
def prodtest_only
return true if Rails.deploy_env?(:prodtest)

redirect_to "/404"
end
end
197 changes: 197 additions & 0 deletions app/controllers/test/load_test_api_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# frozen_string_literal: true

require "./scripts/enable_features_dev"
require "digest"
require "securerandom"
require "base64"
class Test::LoadTestApiController < Api::ApplicationController
include ProdtestOnlyConcern

API_KEY_CACHE_KEY = "load_test_api_key"
IDT_TOKEN_CACHE_KEY = "load_test_idt_token"
LOAD_TESTING_USER = "LOAD_TESTER"

def user
set_current_user

render json: {
idt_token: generate_idt_token
}
end

def target
begin
params.require(:target_type)
render json: {
data_type: params[:target_type],
data: data_for_testing
}
rescue ActiveRecord::RecordNotFound
render json: {
message: "Data returned nil when trying to find #{params[:target_type]}"
}, status: :not_found
end
end

private

def load_test_user
User.find_or_initialize_by(css_id: LOAD_TESTING_USER)
end

# Private: Using the data entered by the user for the target_type and target_id,
# returns an appropriate target_id for the test
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
def data_for_testing
case params[:target_type]
when "Appeal"
target_data_type = Appeal
target_data_column = "uuid"
when "LegacyAppeal"
target_data_type = LegacyAppeal
target_data_column = "vacols_id"
when "Hearing"
target_data_type = Hearing
target_data_column = "uuid"
when "HigherLevelReview"
target_data_type = HigherLevelReview
target_data_column = "uuid"
when "SupplementalClaim"
target_data_type = SupplementalClaim
target_data_column = "uuid"
when "Document"
target_data_type = Document
target_data_column = "id"
when "Metric"
target_data_type = Metric
target_data_column = "uuid"
end

get_target_data_id(params[:target_id], target_data_type, target_data_column)
end
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength

# Private: If no target_id is provided, use the target_id of sample data instead
# Returns the target_data_id of each target_data_type
# For Metric returns the entire target_data object
def get_target_data_id(target_id, target_data_type, target_data_column)
target_data_id = if target_data_type.to_s == "Metric"
target_id.presence ? Metric.find_by_uuid(target_id) : target_data_type.all.sample
elsif target_id.presence
target_data_type.find_by("#{target_data_column}": target_id).nil? ? nil : target_id
else
target_data_type.all.sample[target_data_column.to_sym]
end

if target_data_id.nil?
fail ActiveRecord::RecordNotFound.new(
message: "Data returned nil when trying to find #{params[:target_type]}"
)
end

target_data_id
end

# Private: Finds or creates the user for load testing, makes them a system admin
# so that it can access any area in Caseflow, and stores their information in the
# current session. This will be reflected in the session cookie.
def set_current_user
params.require(:user).tap do |user_requirement|
user_requirement.require([:station_id])
user_requirement.require([:regional_office])
end
user = user.presence || load_test_user
save_user_params(user, params[:user])

grant_or_deny_functions(params[:user][:functions])

add_user_to_org(params[:user][:organizations], user)

enable_or_disable_feature_toggles(params[:user][:feature_toggles], user)

save_session(user)
end

# Private: Assign the user_params to the user and save the updates
# Params: user, user_params
# Response: None
def save_user_params(user, user_params)
user.station_id = user_params[:station_id]
user.selected_regional_office = user_params[:regional_office]
user.roles = user_params[:roles]
user.save
end

# Private: Method to grant or deny specific functions to the LOAD_TESTING_USER
# Params: functions
# Response: None
def grant_or_deny_functions(functions)
functions.select { |_k, v| v == true }.each do |k, _v|
Functions.grant!(k, users: [LOAD_TESTING_USER])
end
functions.select { |_k, v| v == false }.each do |k, _v|
Functions.deny!(k, users: [LOAD_TESTING_USER])
end
end

# Private: Method to add the LOAD_TESTING_USER to specific organizations,
# and adding them as an admin where necessary
# Params: organizations
# Response: None
def add_user_to_org(organizations, user)
remove_user_from_all_organizations

organizations.select { |organization| organization[:admin] == true || "true" }.each do |org|
organization = Organization.find_by_name_or_url(org[:url])
organization.add_user(user) unless organization.users.include?(user)
OrganizationsUser.make_user_admin(user, organization)
end
organizations.select { |organization| organization[:admin] == false || "false" }.each do |org|
organization = Organization.find_by_name_or_url(org[:url])
organization.add_user(user) unless organization.users.include?(user)
end
end

# Private: Method to remove user from all organizations before adding back to only relevant orgs for this test run
# Params: None
# Response: None
def remove_user_from_all_organizations
Organization.all.each do |organization|
OrganizationsUser.remove_user_from_organization(load_test_user, organization)
end
end

# Private: Method to enable or disable feature toggles for the LOAD_TESTING_USER
# Params: feature_toggles
# Response: None
def enable_or_disable_feature_toggles(feature_toggles, user)
feature_toggles.select { |_key, value| value == true }.each do |key, _value|
FeatureToggle.enable!(key, users: [LOAD_TESTING_USER]) if !FeatureToggle.enabled?(key, user: user)
end
feature_toggles.select { |_key, value| value == false }.each do |key, _value|
FeatureToggle.disable!(key, users: [LOAD_TESTING_USER])
end
end

# Private: Method to save the current_user's session cookie
# Params: user
# Response: None
def save_session(user)
session[:user] = user.to_session_hash
session[:regional_office] = user.selected_regional_office
end

# Private: Returns an IDT token if one has already been generated for load testing.
# If one is not available then one will be generated and persisted to the cache.
def generate_idt_token
Rails.cache.fetch(IDT_TOKEN_CACHE_KEY) do
intake_user = User.all.find(&:intake_user?)

key, token = Idt::Token.generate_one_time_key_and_proposed_token

Idt::Token.activate_proposed_token(key, intake_user.css_id)

token
end
end
end
Loading
Loading