Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
873e898
Merge branch '4.0.0-dev' of https://github.com/themeum/tutor into har…
harunollyo Jun 15, 2026
e39dadc
fix: quiz attempt security issue
harunollyo Jun 16, 2026
df5aea3
fix: remove redundant user ID parameter from quiz attempt documentation
harunollyo Jun 16, 2026
017c6f9
fix: security issue fix for quiz update
harunollyo Jun 16, 2026
8d468f3
fix: create and reply lesson comment security issue
harunollyo Jun 16, 2026
6d4bbfa
fix: update version to 3.9.13 and patch multiple security vulnerabili…
harunollyo Jun 17, 2026
6cd3557
removed unused code
harunollyo Jun 17, 2026
7ba626b
cs fix and consistent permission checking added
harunollyo Jun 17, 2026
f72ec78
fix: streamline ABSPATH check in Admin and Ajax classes
harunollyo Jun 18, 2026
84737a0
refactor: update login transient expiration and standardize nonce ver…
harunollyo Jun 18, 2026
523c90d
Security Fix: Prevent arbitrary access to course content
harunollyo Jun 18, 2026
00a1852
fix: restrict lesson completion tracking to enrolled users and remove…
harunollyo Jun 18, 2026
ae52ff0
fix: correct spelling of announcement in Ajax class methods
harunollyo Jun 18, 2026
38aa65f
fix: improve code readability by standardizing comments and formattin…
harunollyo Jun 18, 2026
94b2a78
fix: standardize comments and improve code readability in Course_Filt…
harunollyo Jun 18, 2026
49bd166
fix: improve code readability and standardize comments in Course_List…
harunollyo Jun 18, 2026
8bbecdf
removed unused method
harunollyo Jun 18, 2026
4c06d9d
fix: correct spelling of 'Tabs' in Course_Settings_Tabs class comment
harunollyo Jun 18, 2026
8b93890
fix: enhance course ID validation and improve error handling in Cours…
harunollyo Jun 18, 2026
395b9d8
fix: correct spelling in Custom Validation trait and enforce strict c…
harunollyo Jun 18, 2026
c54a925
refactor: fix typo in prepare_bulk_actions method and clean up instru…
harunollyo Jun 19, 2026
c338bdb
refactor: simplify lesson detail and save AJAX handlers using respons…
harunollyo Jun 19, 2026
813dd5b
refactor: update lesson management authorization to include ID valida…
harunollyo Jun 19, 2026
b28943b
resolve merge conflict
harunollyo Jun 19, 2026
5477eb7
refactor: clean up docblock formatting and optimize ABSTPATH check in…
harunollyo Jun 19, 2026
ff3886d
fix: enforce course enrollment validation before lesson completion an…
harunollyo Jun 19, 2026
52f5ed9
Merge branch '4.0.0-dev' of https://github.com/themeum/tutor into har…
harunollyo Jun 19, 2026
4bf6a13
refactor: improve lesson access validation and error handling using s…
harunollyo Jun 22, 2026
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
5 changes: 5 additions & 0 deletions assets/src/js/front/tutor-front.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,11 @@ jQuery(document).ready(function($) {
return;
}

// If user is not enrolled like lesson preview.
if (!video_data.is_enrolled) {
return;
}

if (this.isRequiredPercentage()) {
this.enable_complete_lesson_btn(instance);
}
Expand Down
13 changes: 8 additions & 5 deletions classes/Addons.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@

namespace TUTOR;

if ( ! defined( 'ABSPATH' ) ) {
exit;
}
defined( 'ABSPATH' ) || exit;

/**
* Addons Class
*
Expand All @@ -25,6 +24,7 @@ class Addons {
* Constructor
*
* @since 1.0.0
*
* @return void
*/
public function __construct() {
Expand Down Expand Up @@ -52,6 +52,7 @@ public static function get_addons_config() {
*
* @param string $basename basename of addon.
* @param bool $status status 0,1.
*
* @return void
*/
public static function update_addon_status( $basename, $status ) {
Expand All @@ -66,6 +67,7 @@ public static function update_addon_status( $basename, $status ) {
* Get all addons data.
*
* @since 1.0.0
*
* @return void
*/
public function get_all_addons() {
Expand Down Expand Up @@ -179,8 +181,8 @@ public function addon_enable_disable() {

tutor_utils()->checking_nonce();

if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
if ( ! User::is_admin() ) {
wp_send_json_error( tutor_utils()->error_message() );
}

$form_data = json_decode( Input::post( 'addonFieldNames' ) );
Expand Down Expand Up @@ -227,6 +229,7 @@ public function addon_enable_disable() {
* Get tutor addons list
*
* @since 1.0.0
*
* @return array
*/
public function addons_lists_to_show() {
Expand Down
6 changes: 2 additions & 4 deletions classes/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,14 @@

namespace TUTOR;

defined( 'ABSPATH' ) || exit;

use Tutor\Ecommerce\OrderController;
use Tutor\Helpers\HttpHelper;
use TUTOR\Input;
use Tutor\Models\CourseModel;
use Tutor\Traits\JsonResponse;

if ( ! defined( 'ABSPATH' ) ) {
exit;
}

/**
* Admin Class
*
Expand Down Expand Up @@ -58,7 +56,7 @@
// Handle flash toast message for redirect_to util helper.
add_action( 'admin_head', array( new Utils(), 'handle_flash_message' ), 999 );

add_action( 'admin_bar_menu', array( $this, 'add_toolbar_items' ), 100 );

Check failure on line 59 in classes/Admin.php

View workflow job for this annotation

GitHub Actions / phpstan

Action callback returns mixed but should not return anything.

Check failure on line 59 in classes/Admin.php

View workflow job for this annotation

GitHub Actions / phpstan

Action callback returns mixed but should not return anything.

add_action( 'wp_ajax_tutor_do_not_show_feature_page', array( $this, 'handle_do_not_show_feature_page' ) );

Expand Down Expand Up @@ -262,7 +260,7 @@
'menu_title' => __( 'Tools', 'tutor' ),
'capability' => 'manage_tutor',
'menu_slug' => 'tutor-tools',
'callback' => array( new Tools_V2(), 'load_tools_page' ),

Check failure on line 263 in classes/Admin.php

View workflow job for this annotation

GitHub Actions / phpstan

Class Tutor\Tools_V2 referenced with incorrect case: TUTOR\Tools_V2.

Check failure on line 263 in classes/Admin.php

View workflow job for this annotation

GitHub Actions / phpstan

Class Tutor\Tools_V2 referenced with incorrect case: TUTOR\Tools_V2.
),
'settings' => array(
'parent_slug' => 'tutor',
Expand All @@ -270,7 +268,7 @@
'menu_title' => __( 'Settings', 'tutor' ),
'capability' => 'manage_tutor',
'menu_slug' => 'tutor_settings',
'callback' => array( new Options_V2(), 'load_settings_page' ),

Check failure on line 271 in classes/Admin.php

View workflow job for this annotation

GitHub Actions / phpstan

Class Tutor\Options_V2 referenced with incorrect case: TUTOR\Options_V2.

Check failure on line 271 in classes/Admin.php

View workflow job for this annotation

GitHub Actions / phpstan

Class Tutor\Options_V2 referenced with incorrect case: TUTOR\Options_V2.
),
'license' => null,
'whats_new' => null,
Expand Down Expand Up @@ -348,7 +346,7 @@
*/
public function feature_promotion_page() {
include tutor()->path . 'views/pages/welcome.php';
// include tutor()->path . 'views/pages/feature-promotion.php';

Check failure on line 349 in classes/Admin.php

View workflow job for this annotation

GitHub Actions / WPCS

Inline comments must end in full-stops, exclamation marks, or question marks
}

/**
Expand Down Expand Up @@ -513,7 +511,7 @@
* @return void
*/
public function filter_posts_for_instructors() {
if ( ! current_user_can( 'administrator' ) && current_user_can( tutor()->instructor_role ) ) {

Check failure on line 514 in classes/Admin.php

View workflow job for this annotation

GitHub Actions / WPCS

Capabilities should be used instead of roles. Found "administrator" in function call to current_user_can()
@remove_menu_page( 'edit-comments.php' ); // Comments.
add_filter( 'posts_clauses_request', array( $this, 'posts_clauses_request' ) );
}
Expand Down Expand Up @@ -559,7 +557,7 @@
* @return void
*/
public function check_if_current_users_post() {
if ( current_user_can( 'administrator' ) || ! current_user_can( tutor()->instructor_role ) ) {

Check failure on line 560 in classes/Admin.php

View workflow job for this annotation

GitHub Actions / WPCS

Capabilities should be used instead of roles. Found "administrator" in function call to current_user_can()
return;
}

Expand Down
44 changes: 18 additions & 26 deletions classes/Ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@

namespace TUTOR;

if ( ! defined( 'ABSPATH' ) ) {
exit;
}
defined( 'ABSPATH' ) || exit;

use Tutor\GDPR\Controllers\LegalConsent;
use Tutor\Helpers\HttpHelper;
Expand All @@ -28,6 +26,7 @@
use JsonResponse;

const LOGIN_ERRORS_TRANSIENT_KEY = 'tutor_login_errors';

/**
* Constructor
*
Expand All @@ -41,7 +40,6 @@
public function __construct( $allow_hooks = true ) {
if ( $allow_hooks ) {
add_action( 'wp_ajax_sync_video_playback', array( $this, 'sync_video_playback' ) );
add_action( 'wp_ajax_nopriv_sync_video_playback', array( $this, 'sync_video_playback_noprev' ) );
add_action( 'wp_ajax_tutor_place_rating', array( $this, 'tutor_place_rating' ) );
add_action( 'wp_ajax_delete_tutor_review', array( $this, 'delete_tutor_review' ) );

Expand All @@ -60,8 +58,8 @@
*
* @since v.1.7.9
*/
add_action( 'wp_ajax_tutor_announcement_create', array( $this, 'create_or_update_annoucement' ) );
add_action( 'wp_ajax_tutor_announcement_delete', array( $this, 'delete_annoucement' ) );
add_action( 'wp_ajax_tutor_announcement_create', array( $this, 'create_or_update_announcement' ) );
add_action( 'wp_ajax_tutor_announcement_delete', array( $this, 'delete_announcement' ) );

add_action( 'wp_ajax_tutor_youtube_video_duration', array( $this, 'ajax_youtube_video_duration' ) );
}
Expand All @@ -73,6 +71,7 @@
* Update video information and data when necessary
*
* @since 1.0.0
*
* @return void
*/
public function sync_video_playback() {
Expand Down Expand Up @@ -116,15 +115,6 @@
exit();
}

/**
* Video playback callback for noprev
*
* @since 1.0.0
* @return void
*/
public function sync_video_playback_noprev() {
}

/**
* Place rating
*
Expand Down Expand Up @@ -396,9 +386,7 @@
* Process tutor login
*
* @since 1.6.3
*
* @since 2.1.3 Ajax removed, validation errors
* stores in session.
* @since 2.1.3 Ajax removed, validation errors stores in session.
*
* @return void
*/
Expand All @@ -411,9 +399,9 @@
*
* @since 2.1.4
*/
if ( ! wp_verify_nonce( $_POST[ tutor()->nonce ], tutor()->nonce_action ) ) { //phpcs:ignore
if ( ! tutor_utils()->is_nonce_verified( 'post' ) ) {
$validation_error->add( 401, __( 'Nonce verification failed', 'tutor' ) );
\set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages() );
\set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages(), MINUTE_IN_SECONDS );
return;
}

Expand All @@ -425,10 +413,12 @@
*
* @see https://developer.wordpress.org/reference/functions/wp_signon/
*/
$username = tutor_utils()->array_get( 'log', $_POST ); //phpcs:ignore
$password = tutor_utils()->array_get( 'pwd', $_POST ); //phpcs:ignore
//phpcs:disable WordPress.Security.NonceVerification.Missing
$username = tutor_utils()->array_get( 'log', $_POST ); //phpcs:ignore
$password = tutor_utils()->array_get( 'pwd', $_POST ); //phpcs:ignore
$redirect_to = isset( $_POST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_POST['redirect_to'] ) ) : '';
$remember = isset( $_POST['rememberme'] );
//phpcs:enable WordPress.Security.NonceVerification.Missing

try {
$creds = array(
Expand All @@ -452,7 +442,7 @@
);
}

$validate_consent = LegalConsent::validate_consent( LegalConsent::DISPLAY_ON_LOGIN, $_POST );

Check failure on line 445 in classes/Ajax.php

View workflow job for this annotation

GitHub Actions / WPCS

Processing form data without nonce verification.
if ( is_wp_error( $validate_consent ) ) {
$validation_error->add(
$validate_consent->get_error_code(),
Expand Down Expand Up @@ -497,25 +487,26 @@
$validation_error->add( 400, $e->getMessage() );
} finally {
// Store errors in transient data.
\set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages() );
\set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages(), MINUTE_IN_SECONDS );
}
}

/**
* Create/Update announcement
*
* @since 1.7.9
*
* @return void
*/
public function create_or_update_annoucement() {
public function create_or_update_announcement() {
tutor_utils()->checking_nonce();

$error = array();
$course_id = Input::post( 'tutor_announcement_course' );
$announcement_title = Input::post( 'tutor_announcement_title' );
$announcement_summary = Input::post( 'tutor_announcement_summary', '', Input::TYPE_TEXTAREA );

// Check if user can manage this announcment.
// Check if user can manage this announcement.
if ( ! tutor_utils()->can_user_manage( 'course', $course_id ) ) {
wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
}
Expand Down Expand Up @@ -588,9 +579,10 @@
* Delete announcement
*
* @since 1.7.9
*
* @return void
*/
public function delete_annoucement() {
public function delete_announcement() {
tutor_utils()->checking_nonce();

$announcement_id = Input::post( 'announcement_id' );
Expand Down
10 changes: 6 additions & 4 deletions classes/Announcements.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@

namespace TUTOR;

defined( 'ABSPATH' ) || exit;

use Tutor\Helpers\QueryHelper;
use Tutor\Helpers\UrlHelper;

if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Announcements class
*
Expand All @@ -41,6 +40,7 @@ class Announcements {
* Constructor
*
* @since 1.0.0
*
* @return void
*/
public function __construct() {
Expand Down Expand Up @@ -74,6 +74,7 @@ public function __get( $name ) {
* Prepare bulk actions that will show on dropdown options
*
* @since 2.0.0
*
* @return array
*/
public function prepare_bulk_actions(): array {
Expand All @@ -88,6 +89,7 @@ public function prepare_bulk_actions(): array {
* Handle bulk action for enrollment cancel | delete
*
* @since 2.0.0
*
* @return string JSON response.
*/
public function announcement_bulk_action() {
Expand Down Expand Up @@ -118,7 +120,7 @@ function ( $announcement_id ) {
* @since 2.0.0
*
* @param string $action hold action.
* @param string $bulk_ids comma seperated ids.
* @param string $bulk_ids comma separated ids.
*
* @return bool
*/
Expand Down
Loading
Loading