Skip to content

Commit 9550802

Browse files
committed
partial support for rails layouts
1 parent 8e1b48e commit 9550802

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

ql/lib/codeql/ruby/frameworks/ActionController.qll

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class ActionControllerActionMethod extends Method, HTTP::Server::RequestHandler:
6969
* `<sourcePrefix>app/views/<subpath>/<method_name>.html.erb`.
7070
*/
7171
ErbFile getDefaultTemplateFile() {
72-
controllerTemplatesFolder(this.getControllerClass(), result.getParentContainer()) and
72+
controllerTemplateFile(this.getControllerClass(), result) and
7373
result.getBaseName() = this.getName() + ".html.erb"
7474
}
7575

@@ -220,25 +220,40 @@ class ActionControllerHelperMethod extends Method {
220220
* if such a controller class exists.
221221
*/
222222
ActionControllerControllerClass getAssociatedControllerClass(ErbFile f) {
223-
controllerTemplatesFolder(result, f.getParentContainer())
223+
// There is a direct mapping from template file to controller class
224+
controllerTemplateFile(result, f)
225+
or
226+
// The template `f` is a partial, and it is rendered from within another
227+
// template file, `fp`. In this case, `f` inherits the associated
228+
// controller classes from `fp`.
229+
f.isPartial() and
230+
exists(RenderCall r, ErbFile fp |
231+
r.getLocation().getFile() = fp and
232+
r.getTemplateFile() = f and
233+
result = getAssociatedControllerClass(fp)
234+
)
224235
}
225236

237+
// TODO: improve layout support, e.g. for `layout` method
238+
// https://guides.rubyonrails.org/layouts_and_rendering.html
226239
/**
227-
* Holds if `templatesFolder` is in the correct location to contain template
228-
* files "belonging" to the given `ActionControllerControllerClass`, according
229-
* to Rails conventions.
240+
* Holds if `templatesFile` is a viable file "belonging" to the given
241+
* `ActionControllerControllerClass`, according to Rails conventions.
230242
*
231-
* In particular, this means that an action method in `cls` will by default
232-
* render a correspondingly named template file within `templatesFolder`.
243+
* This handles mappings between controllers in `app/controllers/`, and
244+
* templates in `app/views/` and `app/views/layouts/`.
233245
*/
234-
predicate controllerTemplatesFolder(ActionControllerControllerClass cls, Folder templatesFolder) {
246+
predicate controllerTemplateFile(ActionControllerControllerClass cls, ErbFile templateFile) {
235247
exists(string templatesPath, string sourcePrefix, string subPath, string controllerPath |
236248
controllerPath = cls.getLocation().getFile().getRelativePath() and
237-
templatesPath = templatesFolder.getRelativePath() and
249+
templatesPath = templateFile.getParentContainer().getRelativePath() and
238250
// `sourcePrefix` is either a prefix path ending in a slash, or empty if
239251
// the rails app is at the source root
240252
sourcePrefix = [controllerPath.regexpCapture("^(.*/)app/controllers/(?:.*?)/(?:[^/]*)$", 1), ""] and
241253
controllerPath = sourcePrefix + "app/controllers/" + subPath + "_controller.rb" and
242-
templatesPath = sourcePrefix + "app/views/" + subPath
254+
(
255+
templatesPath = sourcePrefix + "app/views/" + subPath or
256+
templateFile.getRelativePath().matches(sourcePrefix + "app/views/layouts/" + subPath + "%")
257+
)
243258
)
244259
}

0 commit comments

Comments
 (0)