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

Up to deep linking #552

Merged
merged 8 commits into from
Mar 31, 2023
Merged
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
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ GEM
nio4r (~> 2.0)
pyu-ruby-sasl (0.0.3.3)
racc (1.6.2)
rack (2.2.6.3)
rack (2.2.6.4)
rack-oauth2 (1.21.3)
activesupport
attr_required
Expand Down
68 changes: 67 additions & 1 deletion app/controllers/components_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class ComponentsController < ApplicationController
before_action :set_component, only: %i[show update destroy export]
before_action :set_project, only: %i[show create]
before_action :set_component_permissions, only: %i[show]
before_action :set_rule, only: %i[show]
before_action :authorize_admin_project, only: %i[create]
before_action :authorize_admin_component, only: %i[destroy]
before_action :authorize_author_component, only: %i[update]
Expand Down Expand Up @@ -256,13 +257,78 @@ def create_or_duplicate
end
end

# Defines the set_component method.
def set_component
# Loads a Component object with associated rules, reviews,
# descriptions, checks and additional answers where ID is equal to params id.
@component = Component.eager_load(
rules: [:reviews, :disa_rule_descriptions, :rule_descriptions, :checks,
:additional_answers, :satisfies, :satisfied_by, {
srg_rule: %i[disa_rule_descriptions rule_descriptions checks]
}]
).find(params[:id])
).find_by(id: params[:id])

# Returns out of the method If the Component instance variable does exist.
return if @component.present?

message = 'The requested component could not be found.'
respond_to do |format|
# Return an HTML response with an alert flash message if request format is HTML.
format.html do
flash.alert = message
redirect_back(fallback_location: root_path)
end
# Return a JSON response with a toast message if request formt is JSON.
format.json do
render json: {
toast: {
title: 'Control not found',
message: message,
variant: 'danger'
}
}, status: :not_found
end
end
end

# This function sets the rule based on the specified parameters
def set_rule
# Extracts the last 6 digits from the stig_id parameter
stig_id = params[:stig_id]&.last(6)

# Returns out of the function if stig ID is blank or empty
return if stig_id.blank?

# Queries the Rule model with component_id and rule_id as arguments to find a specific rule.
@rule = Rule.find_by(component_id: params[:id], rule_id: stig_id)

# If a record for the rule exists, set the instance variable @rule_json to the rule's JSON attribute
if @rule.present?
@rule_json = @rule.to_json

# Else, create an error message and respond to either HTML or JSON requests
else
message = 'The requested component and control combination could not be found.'
respond_to do |format|
flash.alert = message

# If html format is requested, redirect back to default page
format.html do
redirect_back(fallback_location: root_path)
end
format.json do
# Render a json response in a toast message format
# as well as setting status code of the response to not_found (404)
render json: {
toast: {
title: 'Control not found',
message: message,
variant: 'danger'
}
}, status: :not_found
end
end
end
end

def set_project
Expand Down
33 changes: 27 additions & 6 deletions app/javascript/components/components/ProjectComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,12 @@ export default {
SortRulesMixin,
],
props: {
queriedRule: {
type: Object,
default() {
return {};
},
},
effective_permissions: {
type: String,
},
Expand Down Expand Up @@ -427,6 +433,12 @@ export default {
localStorage.removeItem(`componentTabIndex-${this.component.id}`);
}
}
// Set selectedRule to the queried rule if present
if (this.queriedRule.id) {
this.selectedRule = this.queriedRule;
this.componentSelectedRuleId = this.selectedRule.id;
window.history.pushState({}, "", `/components/${this.component.id}`);
}
},
methods: {
refreshComponent: function () {
Expand Down Expand Up @@ -455,12 +467,21 @@ export default {
}
},
updateSelectedRule: function (rule) {
axios
.get(`/rules/${rule.id}`)
.then((response) => {
this.selectedRule = response.data;
})
.catch(this.alertOrNotifyResponse);
if (this.queriedRule.id) {
return;
}
if (rule) {
axios
.get(`/rules/${rule.id}`)
.then((response) => {
this.selectedRule = response.data;
this.componentSelectedRuleId = this.selectedRule.id;
})
.catch(this.alertOrNotifyResponse);
} else {
this.selectedRule = {};
this.componentSelectedRuleId = null;
}
},
handleRuleSelected: function (ruleId) {
this.componentSelectedRuleId = ruleId;
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/components/project/DiffViewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ export default {
this.ruleDeselected();
if (this.baseComponent) {
axios
.get(`/components/${this.baseComponent.id}/based_on_same_srg`)
.get(`/components/${this.baseComponent.id}/search/based_on_same_srg`)
.then((response) => {
this.compareList = response.data;
})
Expand Down
11 changes: 10 additions & 1 deletion app/javascript/components/rules/RuleEditorHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
<i v-if="rule.locked" class="mdi mdi-lock" aria-hidden="true" />
<i v-if="rule.review_requestor_id" class="mdi mdi-file-find" aria-hidden="true" />
<i v-if="rule.changes_requested" class="mdi mdi-delta" aria-hidden="true" />
{{ `${projectPrefix}-${rule.rule_id}` }} // {{ rule.version }}
<a
class="headerLink"
:href="`/components/${rule.component_id}/${projectPrefix}-${rule.rule_id}`"
>
{{ `${projectPrefix}-${rule.rule_id}` }} // {{ rule.version }}
</a>
</h2>

<p v-if="!readOnly && rule.locked" class="text-danger font-weight-bold">
Expand Down Expand Up @@ -499,4 +504,8 @@ export default {
width: 0;
margin-top: 0.25rem;
}

.headerLink {
color: inherit;
}
</style>
14 changes: 10 additions & 4 deletions app/models/disa_rule_description.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,17 @@ def self.from_mapping(disa_rule_description_mapping)
# retry once
retried = false
begin
parsed_mapping = Hash.from_xml(disa_rule_description_mapping)
# Customize the Nokogiri parser options to attempt to recover from syntax errors while
# also disabling character entity parsing.
options = Nokogiri::XML::ParseOptions::RECOVER | Nokogiri::XML::ParseOptions::NOENT
# Parse the XML with custom options
doc = Nokogiri::XML(disa_rule_description_mapping, nil, nil, options)
# Convert the Nokogiri document to a Ruby Hash
parsed_mapping = Hash.from_xml(doc.to_xml)
# parsed_mapping = Hash.from_xml(disa_rule_description_mapping)
rescue ::REXML::ParseException => e
unless e.continued_exception.is_a?(RuntimeError) && !retried && (
e.continued_exception.message.include?('"&"') || e.continued_exception.message.include?('"<"')
)
unless e.continued_exception.is_a?(RuntimeError) && !retried &&
(e.continued_exception.message.include?('"&"') || e.continued_exception.message.include?('"<"'))
raise
end

Expand Down
1 change: 1 addition & 0 deletions app/views/components/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#projectcomponent
%projectcomponent{ |
'v-bind:queried-rule': @rule_json, |
'v-bind:effective_permissions': @effective_permissions.to_json, |
'v-bind:initial-component-state': @component_json, |
'v-bind:project': @project_json, |
Expand Down
6 changes: 5 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@
resources :rule_satisfactions, only: %i[create destroy]
# Alias rules#index to controls for convenience
get '/components/:component_id/controls', to: 'rules#index'

# Add deep linking to specific rule (stig_id of format XXXX-XX-000000)
get '/components/:id/:stig_id', to: 'components#show'

# Make components#index not a child of project
get '/components', to: 'components#index'
# Revision history between components
post '/components/history', to: 'components#history'
# Export component
get '/components/:id/export/:type', to: 'components#export'
# Components based on same srg
get '/components/:id/based_on_same_srg', to: 'components#based_on_same_srg'
get '/components/:id/search/based_on_same_srg', to: 'components#based_on_same_srg'
# Compare components
get '/components/:id/compare/:diff_id', to: 'components#compare'
# Find
Expand Down