Skip to content

Commit a1e9923

Browse files
bpamiriclaude
andcommitted
fix: Revert broken parameterized queries in Controller and BlogController
Wheels findOne/findAll do not support a `params` argument — the `:placeholder` syntax with `params={}` is silently ignored, making WHERE clauses match literal `:slug` text instead of actual values. Revert to Wheels' standard string interpolation in where clauses, which the framework auto-parameterizes via prepared statements. Other controllers (AuthController, BookmarkController, etc.) still have the same broken params pattern and need separate fixes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 6a9c366 commit a1e9923

File tree

2 files changed

+12
-19
lines changed

2 files changed

+12
-19
lines changed

app/controllers/Controller.cfc

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ component extends="wheels.Controller" {
6565
var accesspermission = model("RolePermission").findAll(
6666
select="roleId, permissionId, name, permissionName, permissionstatus, controller, permissiondescription",
6767
include="Role, Permission",
68-
where="name = :roleName AND permissions.Name = :actionName AND permissions.controller = :controllerName",
69-
params={roleName={value=session.role, cfsqltype="cf_sql_varchar"}, actionName={value=action, cfsqltype="cf_sql_varchar"}, controllerName={value=controller, cfsqltype="cf_sql_varchar"}}
68+
where="name = '#session.role#' AND permissions.Name = '#action#' AND permissions.controller = '#controller#'"
7069
);
7170
if(accesspermission.recordCount == 0){
7271
if (structKeyExists(getHttpRequestData().headers, "HX-Request")) {
@@ -103,17 +102,15 @@ component extends="wheels.Controller" {
103102
// Shared business logic across multiple controllers
104103
public function getBlogBySlug(required string slug) {
105104
return model("Blog").findOne(
106-
where="blog_posts.slug = :slug AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= :now",
107-
params={slug={value=arguments.slug, cfsqltype="cf_sql_varchar"}, now={value=now(), cfsqltype="cf_sql_timestamp"}},
105+
where="blog_posts.slug = '#arguments.slug#' AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= '#now()#'",
108106
include="User",
109107
cache=10
110108
);
111109
}
112110

113111
function getTagsByBlogid(required numeric id) {
114112
return model("BlogTag").findAll(
115-
where="blogId = :blogId",
116-
params={blogId={value=arguments.id, cfsqltype="cf_sql_integer"}},
113+
where="blogId = #arguments.id#",
117114
include="Tag",
118115
cache=10
119116
);
@@ -122,8 +119,7 @@ component extends="wheels.Controller" {
122119

123120
function getCategoriesByBlogid(required numeric id) {
124121
return model("BlogCategory").findAll(
125-
where = "blogId = :blogId",
126-
params = {blogId={value=arguments.id, cfsqltype="cf_sql_integer"}},
122+
where = "blogId = #arguments.id#",
127123
include = "Blog,Category",
128124
cache = 10
129125
);
@@ -391,7 +387,7 @@ component extends="wheels.Controller" {
391387
string url = "",
392388
string isSubscriber = ""
393389
) {
394-
var emaildata = model("emailTemplate").findAll(where="title = :templateTitle", params={templateTitle={value=arguments.templateTitle, cfsqltype="cf_sql_varchar"}}, cache=10);
390+
var emaildata = model("emailTemplate").findAll(where="title = '#arguments.templateTitle#'", cache=10);
395391
if (!emaildata.recordCount) return false;
396392
var emailparams = {
397393
"name" = arguments.recipientName,
@@ -448,8 +444,7 @@ component extends="wheels.Controller" {
448444
}
449445

450446
var existingBlog = model("Blog").findFirst(
451-
where="title = :title AND slug = :slug AND id != :blogId",
452-
params={title={value=params.title, cfsqltype="cf_sql_varchar"}, slug={value=params.slug, cfsqltype="cf_sql_varchar"}, blogId={value=blogId, cfsqltype="cf_sql_integer"}}
447+
where="title = '#params.title#' AND slug = '#params.slug#' AND id != #blogId#"
453448
);
454449

455450
if (isObject(existingBlog)) {
@@ -513,7 +508,7 @@ component extends="wheels.Controller" {
513508
function deleteBlogTags(required blogId) {
514509
try {
515510
if (!isEmpty(blogId)) {
516-
model("BlogTag").deleteAll(where="blogId = :blogId", params={blogId={value=arguments.blogId, cfsqltype="cf_sql_integer"}});
511+
model("BlogTag").deleteAll(where="blogId = #arguments.blogId#");
517512
}
518513
} catch (any e) {
519514
model("Log").log(
@@ -536,7 +531,7 @@ component extends="wheels.Controller" {
536531
function deleteBlogCategories(required blogId) {
537532
try {
538533
if (!isEmpty(blogId)) {
539-
model("BlogCategory").deleteAll(where="blogId = :blogId", params={blogId={value=arguments.blogId, cfsqltype="cf_sql_integer"}});
534+
model("BlogCategory").deleteAll(where="blogId = #arguments.blogId#");
540535
}
541536
} catch (any e) {
542537
model("Log").log(

app/controllers/web/BlogController.cfc

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ component extends="app.Controllers.Controller" {
348348
return Val(authorParam);
349349
} else {
350350
// Lookup user by username
351-
var user = model("user").findOne(where = "username = :username", params={username={value=arguments.authorParam, cfsqltype="cf_sql_varchar"}});
351+
var user = model("user").findOne(where = "username = '#arguments.authorParam#'");
352352
if (IsObject(user)) {
353353
return user.id;
354354
} else {
@@ -374,8 +374,7 @@ component extends="app.Controllers.Controller" {
374374
if (Len(Trim(searchTerm))) {
375375
var searchPattern = "%#searchTerm#%";
376376
var query = model("blog").findAll(
377-
where = "blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= '#Now()#' AND (blog_posts.slug LIKE :pattern OR blog_posts.title LIKE :pattern OR blog_posts.content LIKE :pattern OR fullname LIKE :pattern OR email LIKE :pattern)",
378-
params = {pattern={value=searchPattern, cfsqltype="cf_sql_varchar"}},
377+
where = "blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= '#Now()#' AND (blog_posts.slug LIKE '#searchPattern#' OR blog_posts.title LIKE '#searchPattern#' OR blog_posts.content LIKE '#searchPattern#' OR fullname LIKE '#searchPattern#' OR email LIKE '#searchPattern#')",
379378
include = "User",
380379
order = "publishedAt DESC",
381380
page = page,
@@ -385,8 +384,7 @@ component extends="app.Controllers.Controller" {
385384
if (isInfiniteScroll) {
386385
totalCount = model("blog").count(
387386
include = "User",
388-
where = "blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= '#Now()#' AND (blog_posts.slug LIKE :pattern OR blog_posts.title LIKE :pattern OR blog_posts.content LIKE :pattern OR fullname LIKE :pattern OR email LIKE :pattern)",
389-
params = {pattern={value=searchPattern, cfsqltype="cf_sql_varchar"}}
387+
where = "blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= '#Now()#' AND (blog_posts.slug LIKE '#searchPattern#' OR blog_posts.title LIKE '#searchPattern#' OR blog_posts.content LIKE '#searchPattern#' OR fullname LIKE '#searchPattern#' OR email LIKE '#searchPattern#')"
390388
);
391389
hasMore = (page * perPage) < totalCount;
392390
isSearched = true;
@@ -621,7 +619,7 @@ component extends="app.Controllers.Controller" {
621619

622620
// Allow title change and check uniqueness
623621
if (StructKeyExists(params, "title")) {
624-
var existingBlog = model("Blog").findFirst(where = "title = :title AND id != :blogId", params={title={value=params.title, cfsqltype="cf_sql_varchar"}, blogId={value=blogId, cfsqltype="cf_sql_integer"}});
622+
var existingBlog = model("Blog").findFirst(where = "title = '#params.title#' AND id != #blogId#");
625623
if (IsObject(existingBlog)) {
626624
result.success = false;
627625
result.message = "A blog post with this title already exists.";

0 commit comments

Comments
 (0)