Skip to content
This repository was archived by the owner on Apr 21, 2026. It is now read-only.

Commit 6e2270c

Browse files
bpamiriclaude
andcommitted
fix: Enforce publishedAt <= CURRENT_TIMESTAMP for scheduled blog posts
Future-dated blog posts were visible immediately because queries only checked publishedAt IS NOT NULL. Added time comparison to all 17 public-facing queries across blog listing, search, RSS feed, sitemap, category/tag/author/archive views, and news page. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 375064a commit 6e2270c

4 files changed

Lines changed: 17 additions & 17 deletions

File tree

app/controllers/Controller.cfc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ component extends="wheels.Controller" {
102102
// Shared business logic across multiple controllers
103103
public function getBlogBySlug(required string slug) {
104104
return model("Blog").findOne(
105-
where="blog_posts.slug = '#arguments.slug#' AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL",
105+
where="blog_posts.slug = '#arguments.slug#' AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP",
106106
include="User,PostStatus",
107107
cache=10
108108
);

app/controllers/web/BlogController.cfc

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ component extends="app.Controllers.Controller" {
264264
private function getBlogsByAuthor(required authorId, numeric page=1, numeric perPage=6, boolean isInfiniteScroll=false) {
265265
var result = {
266266
query = model("Blog").findAll(
267-
where="blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.createdBy = #arguments.authorId#",
267+
where="blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP AND blog_posts.createdBy = #arguments.authorId#",
268268
include="User",
269269
order="COALESCE(post_created_date, blog_posts.createdat) DESC",
270270
page = arguments.page,
@@ -275,7 +275,7 @@ component extends="app.Controllers.Controller" {
275275
};
276276

277277
result.totalCount = model("Blog").count(
278-
where="blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.createdBy = #arguments.authorId#"
278+
where="blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP AND blog_posts.createdBy = #arguments.authorId#"
279279
);
280280
result.hasMore = (page * perPage) < result.totalCount;
281281

@@ -318,7 +318,7 @@ component extends="app.Controllers.Controller" {
318318
if (len(trim(searchTerm))) {
319319
var searchPattern = "%#searchTerm#%";
320320
var query = model("blog").findAll(
321-
where="blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL 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#')",
321+
where="blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP 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#')",
322322
include="User, PostStatus, PostType",
323323
order = "COALESCE(post_created_date, blog_posts.createdat) DESC",
324324
page = page,
@@ -328,7 +328,7 @@ component extends="app.Controllers.Controller" {
328328
if (isInfiniteScroll) {
329329
totalCount = model("blog").count(
330330
include="User, PostStatus, PostType",
331-
where="blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL 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#')"
331+
where="blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP 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#')"
332332
);
333333
hasMore = (page * perPage) < totalCount;
334334
isSearched = true;
@@ -750,7 +750,7 @@ component extends="app.Controllers.Controller" {
750750
public function feed() {
751751
// Fetch all blogs
752752
blogPosts = model("Blog").findAll(
753-
where="blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL",
753+
where="blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP",
754754
include="User",
755755
order="postDate DESC",
756756
cache=10
@@ -804,7 +804,7 @@ component extends="app.Controllers.Controller" {
804804
private function getAllBlogs(numeric page=1, numeric perPage=6, boolean isInfiniteScroll=false) {
805805
var result = {
806806
query = model("Blog").findAll(
807-
where="blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL",
807+
where="blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP",
808808
include="User",
809809
order="COALESCE(post_created_date, blog_posts.createdat) DESC",
810810
page = arguments.page,
@@ -816,7 +816,7 @@ component extends="app.Controllers.Controller" {
816816
};
817817

818818
result.totalCount = model("Blog").count(
819-
where="blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL",
819+
where="blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP",
820820
cache = 5
821821
);
822822
result.hasMore = (page * perPage) < result.totalCount;
@@ -831,7 +831,7 @@ component extends="app.Controllers.Controller" {
831831

832832
var result = {
833833
query = model("Blog").findAll(
834-
where="blog_posts.post_created_date BETWEEN '#startdate#' AND '#enddate#' AND blog_posts.status='Approved' AND blog_posts.publishedAt IS NOT NULL",
834+
where="blog_posts.post_created_date BETWEEN '#startdate#' AND '#enddate#' AND blog_posts.status='Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP",
835835
order="postCreatedDate DESC",
836836
include="User",
837837
returnAs="query",
@@ -843,7 +843,7 @@ component extends="app.Controllers.Controller" {
843843
};
844844

845845
result.totalCount = model("Blog").count(
846-
where="blog_posts.post_created_date BETWEEN '#startdate#' AND '#enddate#' AND blog_posts.status='Approved' AND blog_posts.publishedAt IS NOT NULL"
846+
where="blog_posts.post_created_date BETWEEN '#startdate#' AND '#enddate#' AND blog_posts.status='Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP"
847847
);
848848
result.hasMore = (page * perPage) < result.totalCount;
849849

@@ -865,7 +865,7 @@ component extends="app.Controllers.Controller" {
865865

866866
var result = {
867867
query = model("Blog").findAll(
868-
where="blog_posts.id IN (#blogIdList#) AND categoryId = #category.id# AND blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL",
868+
where="blog_posts.id IN (#blogIdList#) AND categoryId = #category.id# AND blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP",
869869
order="createdAt DESC",
870870
include="User,BlogCategory",
871871
returnAs="query",
@@ -877,7 +877,7 @@ component extends="app.Controllers.Controller" {
877877
};
878878

879879
result.totalCount = model("Blog").count(
880-
where="blog_posts.id IN (#blogIdList#) AND categoryId = #category.id# AND blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL",
880+
where="blog_posts.id IN (#blogIdList#) AND categoryId = #category.id# AND blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP",
881881
include="User,BlogCategory"
882882
);
883883
result.hasMore = (page * perPage) < result.totalCount;
@@ -889,7 +889,7 @@ component extends="app.Controllers.Controller" {
889889
private function getAllByTag(required string tag, numeric page=1, numeric perPage=6, boolean isInfiniteScroll=false) {
890890
var result = {
891891
query = model("Blog").findAll(
892-
where="name = '#arguments.tag#' AND blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL",
892+
where="name = '#arguments.tag#' AND blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP",
893893
order="createdAt DESC",
894894
include="User,tag",
895895
returnAs="query",
@@ -900,7 +900,7 @@ component extends="app.Controllers.Controller" {
900900
totalCount = 0
901901
};
902902

903-
result.totalCount = model("Blog").count(where="name = '#arguments.tag#' AND blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL", include="User,tag");
903+
result.totalCount = model("Blog").count(where="name = '#arguments.tag#' AND blog_posts.status ='Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP", include="User,tag");
904904
result.hasMore = (page * perPage) < result.totalCount;
905905

906906
return result;

app/controllers/web/HomeController.cfc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ component extends="app.Controllers.Controller" {
216216
});
217217

218218
// Add blog posts
219-
var blogPosts = model("Blog").findAll(where="blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL ");
219+
var blogPosts = model("Blog").findAll(where="blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP ");
220220
for (var post in blogPosts) {
221221
arrayAppend(urls, {
222222
loc: getBaseUrl() & "/blog/" & post.slug,
@@ -231,7 +231,7 @@ component extends="app.Controllers.Controller" {
231231
select="username",
232232
include="User",
233233
distinct="true",
234-
where="blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.createdBy IS NOT NULL"
234+
where="blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP AND blog_posts.createdBy IS NOT NULL"
235235
);
236236
for (var author in authors) {
237237
arrayAppend(urls, {

app/controllers/web/NewsController.cfc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ component extends="app.Controllers.Controller" {
4343
try {
4444
var blogQuery = model("Blog").findAll(
4545
select = "title, slug, content, postDate",
46-
where = "blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL ",
46+
where = "blog_posts.statusId <> 1 AND blog_posts.status = 'Approved' AND blog_posts.publishedAt IS NOT NULL AND blog_posts.publishedAt <= CURRENT_TIMESTAMP ",
4747
order = "createdAt DESC",
4848
cache = 10
4949
);

0 commit comments

Comments
 (0)