PR-6.2-dev Pending

User tests: Successful: Unsuccessful:

avatar CSGoat0
CSGoat0
10 Apr 2026

Pull Request

Pull Request resolves #47370

  • I read the Generative AI policy and my contribution is either not created with the help of AI or is compatible with the policy and GNU/GPL 2 or later.

Summary of Changes

This PR implements a secure, time-limited token-based preview system that allows administrators to preview articles regardless of their publishing date or published state, even when "Shared Sessions" is disabled in Global Configuration.

image

Key changes:

  1. Added a new database table #__content_preview_tokens to store preview tokens with expiration
  2. Modified the preview link generation in the admin article view to include &preview=1 and a unique token
  3. Added isAdminPreview() validation method in the frontend ArticleModel to verify valid preview requests
  4. Bypassed publishing date and state filters for authenticated preview requests

Testing Instructions

Prerequisites:

  • Joomla installation with "Shared Sessions" disabled (Global Configuration → System → Session Settings → Shared Sessions = No)
  • A user account with administrator privileges

Test Scenario 1: Future-dated article preview

  1. Create a new article with "Start Publishing" set to tomorrow's date
  2. Click the Preview button from the article edit form
  3. ✅ Verify the article preview displays correctly (not a 404 error)

Test Scenario 2: Unpublished article preview

  1. Create a new article and set its state to "Unpublished"
  2. Click the Preview button from the article edit form
  3. ✅ Verify the article preview displays correctly

Test Scenario 3: Regular frontend access (regression)

  1. Access a published article normally (without preview=1 parameter)
  2. ✅ Verify the article displays normally with publishing date restrictions applied
  3. Access a future-dated article normally
  4. ✅ Verify the article shows a 404 (correct behavior for public users)

Actual result BEFORE applying this Pull Request

When "Shared Sessions" is disabled:

  • Clicking Preview on a future-dated article displays a 404 - Article not found error
  • Clicking Preview on an unpublished article displays a 404 - Article not found error
  • Administrators must enable "Shared Sessions" for preview to work, which is not ideal for security-conscious sites

Expected result AFTER applying this Pull Request

When "Shared Sessions" is disabled:

  • Clicking Preview on a future-dated article displays the article preview correctly
  • Clicking Preview on an unpublished article displays the article preview correctly
  • Security is maintained through time-limited, cryptographically secure tokens tied to user permissions

Implementation Details

1. New Database Table (#__content_preview_tokens)

CREATE TABLE IF NOT EXISTS `#__content_preview_tokens` (
    `id`         INT(11)      NOT NULL AUTO_INCREMENT,
    `token`      VARCHAR(64)  NOT NULL,
    `user_id`    INT(11)      NOT NULL,
    `article_id` INT(11)      NOT NULL,
    `expires`    DATETIME     NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `idx_token` (`token`),
    KEY `idx_article` (`article_id`),
    KEY `idx_expires` (`expires`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

2. Token Generation (administrator/components/com_content/src/View/Article/HtmlView.php)

  • Generates a cryptographically secure 32-character hex token using random_bytes(16)
  • Token expires after 5 minutes (sufficient for preview, limits replay attacks)
  • Automatically cleans up expired tokens from the database
  • Appends &preview=1&preview_token={token} to both standard preview and accessibility (jooa11y) preview links

3. Token Validation (components/com_content/src/Model/ArticleModel.php)

  • Checks for preview=1 parameter in the request
  • Validates the token exists in the database, matches the article ID, and is not expired
  • Verifies the user associated with the token has core.edit.state permission
  • Returns true only if all validation passes

4. Filter Bypass Logic

  • Date filters (publish_up/publish_down) are skipped when isAdminPreview() returns true
  • State filters (published/unpublished) are skipped when isAdminPreview() returns true
  • Post-query state validation is skipped when isAdminPreview() returns true

Security Considerations

Attack Vector Mitigation
Token guessing 128-bit entropy (2^128 possibilities) makes brute force infeasible
Token interception 5-minute expiration limits the attack window
Token replay Expired tokens are deleted; each preview generates a new token
Unauthorized user Token is tied to the generating user's ID and requires core.edit.state permission
Shared links Users without edit permissions cannot use another user's preview token

Additional Notes

Testing performed:

  • ✅ Future-dated article preview works with Shared Sessions disabled
  • ✅ Unpublished article preview works with Shared Sessions disabled
  • ✅ Expired tokens correctly return 404
  • ✅ Regular frontend article access unaffected (regression test passed)
  • ❌ Accessibility check (jooa11y) is not currently working with the same token mechanism, if this PR is accepted I might follow up with another PR to solve its issue.

Database installation:
The table creation query was tested via phpMyAdmin on an existing Joomla installation.

Note on branch targeting:
I understand that bug fixes are typically made against the 5.4 branch, while new features target 6.2. However, since my solution introduces a new database table and implements a token-based preview system (which adds new functionality to the core), I believe this could be a feature rather than a pure bug fix. Therefore, I have developed this against the 6.2 branch. If the maintainers prefer this to be backported or handled differently, I'm happy to adjust accordingly.

Link to documentations

Please select:

  • Documentation link for guide.joomla.org:
  • No documentation changes for guide.joomla.org needed
  • Pull Request link for manual.joomla.org:
  • No documentation changes for manual.joomla.org needed
avatar CSGoat0 CSGoat0 - open - 10 Apr 2026
avatar CSGoat0 CSGoat0 - change - 10 Apr 2026
Status New Pending
avatar joomla-cms-bot joomla-cms-bot - change - 10 Apr 2026
Category Administration com_content Front End SQL Installation
avatar CSGoat0 CSGoat0 - edited - 10 Apr 2026
avatar CSGoat0 CSGoat0 - edited - 10 Apr 2026
avatar brianteeman
brianteeman - comment - 10 Apr 2026

As you can see from the test this breaks on postgres as you have only updated the installation sql for mysql - you need to do the same change for postgres

You also need to have update sql for existing installations

avatar CSGoat0 CSGoat0 - change - 11 Apr 2026
Labels Added: PR-6.2-dev
avatar joomla-cms-bot joomla-cms-bot - change - 11 Apr 2026
Category Administration com_content Front End SQL Installation Administration com_content Front End SQL Installation Postgresql
avatar joomla-cms-bot joomla-cms-bot - change - 11 Apr 2026
Category Administration com_content Front End SQL Installation Postgresql SQL Administration com_admin Postgresql com_content Front End Installation
avatar CSGoat0 CSGoat0 - change - 11 Apr 2026
The description was changed
avatar CSGoat0 CSGoat0 - edited - 11 Apr 2026
avatar CSGoat0
CSGoat0 - comment - 11 Apr 2026

As you can see from the test this breaks on postgres as you have only updated the installation sql for mysql - you need to do the same change for postgres

You also need to have update sql for existing installations

Hello, thanks for the help!
I have just updated postgresql and sql for existing installations.

avatar CSGoat0 CSGoat0 - change - 11 Apr 2026
The description was changed
avatar CSGoat0 CSGoat0 - edited - 11 Apr 2026
avatar CSGoat0 CSGoat0 - change - 11 Apr 2026
The description was changed
avatar CSGoat0 CSGoat0 - edited - 11 Apr 2026
avatar CSGoat0 CSGoat0 - change - 11 Apr 2026
The description was changed
avatar CSGoat0 CSGoat0 - edited - 11 Apr 2026
avatar CSGoat0 CSGoat0 - change - 11 Apr 2026
Title
Fix unpublished articles preview
[6.2] Fix unpublished articles preview
avatar CSGoat0 CSGoat0 - edited - 11 Apr 2026
avatar CSGoat0 CSGoat0 - change - 11 Apr 2026
The description was changed
avatar CSGoat0 CSGoat0 - edited - 11 Apr 2026
avatar brianteeman
brianteeman - comment - 11 Apr 2026

Accessibility check (jooa11y) is not currently working with the same token mechanism, if this PR is accepted I might follow up with another PR to solve its issue.

That would need to be fixed with this issue

avatar CSGoat0
CSGoat0 - comment - 11 Apr 2026

Accessibility check (jooa11y) is not currently working with the same token mechanism, if this PR is accepted I might follow up with another PR to solve its issue.

That would need to be fixed with this issue

Hello, I found out that accessibility check is not working at 6.2 dev.
The 404 error appears using the original code even at published articles. If it is supposed to work, then probably latest updates broke it.

When I was tracing I found an error Dispatcher not set in Joomla\CMS\Plugin\CMSPlugin, it's because of Deprecated getDispatcher(), when I changed it I found another error and so on.
image

avatar CSGoat0
CSGoat0 - comment - 11 Apr 2026

That would need to be fixed with this issue

Hello, could you please confirm if the accessibility check is not working as it is for me now? (please check my last comment).
If yes, should I try to fix it in this pr? I just thought it would be a little bit out of scope for this issue. I can work on it, but I don't know if this would be correct. So, I am waiting for directions.

avatar brianteeman
brianteeman - comment - 12 Apr 2026

the jooa11y error was unrelated to the changes here and is fixed with #47579

avatar brianteeman
brianteeman - comment - 13 Apr 2026

I will leave it to others with more architecture experience to comment on the code.

From a user experiece this works well and is a good and useful addition to Joomla

avatar CSGoat0
CSGoat0 - comment - 13 Apr 2026

I will leave it to others with more architecture experience to comment on the code.

From a user experiece this works well and is a good and useful addition to Joomla

Thanks! I appreciate that.
Happy to work with Joomla!

I have also fixed another bug yesterday
and made a new PR. I will appreciate feedback.

avatar CSGoat0 CSGoat0 - change - 21 Apr 2026
The description was changed
avatar CSGoat0 CSGoat0 - edited - 21 Apr 2026

Add a Comment

Login with GitHub to post a comment