Skip to content

Commit befbd76

Browse files
authored
Home app - Support for not requiring login (#2883)
* prevent redirect to login if login not required resolves #2881 * Refactors user ID handling in magic URLs Ensures correct user identification when using magic URLs, especially in scenarios where the user is not explicitly logged in. This change centralizes user ID retrieval using `DT_Magic_URL::get_current_user_id` to consistently determine the user based on the magic link's `post_id` and `post_type`. This prevents issues where the wrong user context was being applied, for example when generating the "Home" link or when determining which apps to display. It also updates the launcher to pass the user ID to the magic URL generation functions, so that the correct home link is displayed for the user. * fix claude comments * remove call to undefined function * modify cache-buster version for home-app.js
1 parent 1710a46 commit befbd76

8 files changed

Lines changed: 90 additions & 66 deletions

File tree

dt-apps/dt-home/assets/js/home-app.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class HomeApp {
77
constructor() {
88
// Check authentication before loading content
99
// If user is not authenticated, they will be redirected by PHP before this JavaScript runs
10-
if (jsObject.user_id === 0) {
10+
if (jsObject.user_id === 0 && jsObject.require_login) {
1111
// This should not happen as PHP redirects unauthenticated users
1212
// But as a fallback, redirect to login
1313
const currentUrl = window.location.href;

dt-apps/dt-home/frontend/partials/launcher-bottom-nav.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Only shown on app-type pages (not home screen or link-type apps).
77
*
88
* @var array $apps Array of all apps for the apps selector
9+
* @var int $user_id The current user ID based on the magic link key
910
* @var bool $is_wrapper_context Optional. If true, uses wrapper-specific class names to avoid conflicts.
1011
*/
1112

@@ -46,7 +47,7 @@
4647
<i class="mdi mdi-apps"></i>
4748
<?php esc_html_e( 'Apps', 'disciple_tools' ); ?>
4849
</button>
49-
<a href="<?php echo esc_url( dt_home_magic_url( '' ) ); ?>" class="nav-item nav-item-home" aria-label="<?php esc_attr_e( 'Home', 'disciple_tools' ); ?>">
50+
<a href="<?php echo esc_url( dt_home_magic_url( '', '', $user_id ) ); ?>" class="nav-item nav-item-home" aria-label="<?php esc_attr_e( 'Home', 'disciple_tools' ); ?>">
5051
<i class="mdi mdi-home"></i>
5152
</a>
5253
<a href="<?php echo esc_url( dt_home_get_logout_url() ); ?>" class="nav-item nav-item-logout" aria-label="<?php esc_attr_e( 'Log Out', 'disciple_tools' ); ?>">

dt-apps/dt-home/frontend/partials/launcher-wrapper.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*
88
* @var string $target_app_url The URL of the target app (without launcher parameter)
99
* @var array $apps Array of all apps for the apps selector
10+
* @var int $user_id Current user ID
1011
*/
1112

1213
if ( ! defined( 'ABSPATH' ) ) {
@@ -16,10 +17,6 @@
1617
// Include helper functions
1718
require_once get_template_directory() . '/dt-apps/dt-home/includes/class-home-helpers.php';
1819

19-
// Get all apps for the apps selector
20-
$apps_manager = DT_Home_Apps::instance();
21-
$apps = $apps_manager->get_apps_for_user( get_current_user_id() );
22-
2320
// Mark iframe requests so nested pages can detect they are inside the launcher
2421
$iframe_target_app_url = add_query_arg( 'launcher_iframe', '1', $target_app_url );
2522

dt-apps/dt-home/includes/class-home-apps.php

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -703,10 +703,12 @@ private function determine_app_type( $app ) {
703703
* Get apps for frontend display
704704
*
705705
* @param string|null $type Optional. Filter by app type: 'app', 'link', or null for all apps.
706+
* @param int|null $user_id Optional. Filter by user ID. Defaults to current user.
706707
* @return array Array of apps for frontend display
707708
*/
708-
public function get_apps_for_frontend( $type = null ) {
709+
public function get_apps_for_frontend( $type = null, $user_id = null ) {
709710
$apps = $this->get_enabled_apps();
711+
$user_id = $user_id ?? get_current_user_id();
710712

711713
// Enrich coded magic-link app urls.
712714
$enriched_apps = [];
@@ -724,38 +726,21 @@ public function get_apps_for_frontend( $type = null ) {
724726

725727
if ( isset( $app_meta['post_type'] ) && $app_meta['post_type'] === 'user' ) {
726728
$meta_key = DT_Magic_URL::get_public_key_meta_key( $app_ml_root, $app_ml_type );
727-
$magic_url_key = get_user_option( $meta_key, get_current_user_id() );
729+
$magic_url_key = get_user_option( $meta_key, $user_id );
728730
if ( !empty( $magic_url_key ) ) {
729731
$app['url'] = DT_Magic_URL::get_link_url( $app_ml_root, $app_ml_type, $magic_url_key );
730732
}
731-
} elseif (
732-
isset( $app_meta['root'], $app_meta['post_type'] )
733-
&& 'templates' === strtolower( (string) $app_meta['root'] )
734-
&& in_array( $app_meta['post_type'], [ 'contacts' ], true )
735-
) {
736-
$post_id = Disciple_Tools_Users::get_contact_for_user( get_current_user_id() );
737-
738-
if ( ! empty( $post_id ) ) {
739-
$post = DT_Posts::get_post( $app_meta['post_type'], $post_id );
740-
$meta_key = $app_meta['meta_key'] ?? '';
741-
742-
// Ensure meta_key is set - if not, construct it from root and type
743-
if ( empty( $meta_key ) && ! empty( $app_ml_root ) && ! empty( $app_ml_type ) ) {
744-
$meta_key = $app_ml_root . '_' . $app_ml_type . '_magic_key';
745-
}
746-
747-
if ( ! is_wp_error( $post ) && ! empty( $post ) && ! empty( $meta_key ) ) {
748-
if ( isset( $post[ $meta_key ] ) && ! empty( $post[ $meta_key ] ) ) {
749-
$magic_url_key = $post[ $meta_key ];
750-
} else {
751-
$magic_url_key = dt_create_unique_key();
752-
update_post_meta( $post_id, $meta_key, $magic_url_key );
753-
}
754-
755-
if ( ! empty( $magic_url_key ) ) {
756-
$app['url'] = DT_Magic_URL::get_link_url( $app_ml_root, $app_ml_type, $magic_url_key );
757-
}
758-
}
733+
} else if ( isset( $app_meta['post_type'] ) && $app_meta['post_type'] === 'contacts' ) {
734+
$post_id = get_user_option( 'corresponds_to_contact', $user_id );
735+
$url = DT_Magic_URL::get_link_url_for_post(
736+
$app_meta['post_type'],
737+
$post_id,
738+
$app_ml_root,
739+
$app_ml_type
740+
);
741+
742+
if ( ! empty( $url ) ) {
743+
$app['url'] = $url;
759744
}
760745
}
761746
}
@@ -800,7 +785,7 @@ private function slug_exists( $slug, $apps ) {
800785
* Get apps filtered by user permissions
801786
*/
802787
public function get_apps_for_user( $user_id = 0 ) {
803-
$apps = $this->get_apps_for_frontend();
788+
$apps = $this->get_apps_for_frontend( null, $user_id );
804789
// If roles permissions is not available, return all apps
805790
if ( !class_exists( 'DT_Home_Roles_Permissions' ) ) {
806791
return $apps;

dt-apps/dt-home/includes/class-home-helpers.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@
1717
*
1818
* @param string $action Optional. The action to append to the URL (e.g., 'app/{slug}', 'logout').
1919
* @param string $key Optional. The magic link key. If not provided, uses current user's key.
20+
* @param int|null $user_id Optional. The user ID. Defaults to current user.
2021
* @return string The generated magic URL.
2122
*/
22-
function dt_home_magic_url( $action = '', $key = '' ) {
23+
function dt_home_magic_url( $action = '', $key = '', $user_id = null ) {
2324
// Get the home screen app instance
2425
$home_app = DT_Home_Magic_Link_App::instance();
2526

2627
if ( ! $key ) {
2728
// Get current user's magic link key
28-
$user_id = get_current_user_id();
29+
$user_id = $user_id ?? get_current_user_id();
2930
if ( ! $user_id ) {
3031
return '';
3132
}

dt-apps/dt-home/magic-link-home-app.php

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public function wp_enqueue_scripts() {
132132
// Enqueue menu toggle JavaScript
133133
wp_enqueue_script( 'dt-home-menu-toggle', get_template_directory_uri() . '/dt-apps/dt-home/assets/js/menu-toggle.js', [], '1.0.0', true );
134134

135-
wp_enqueue_script( 'dt-home-app', get_template_directory_uri() . '/dt-apps/dt-home/assets/js/home-app.js', [], '1.0.0', true );
135+
wp_enqueue_script( 'dt-home-app', get_template_directory_uri() . '/dt-apps/dt-home/assets/js/home-app.js', [], '1.0.1', true );
136136

137137
// Pass logout URL and invite settings to menu toggle script
138138
if ( function_exists( 'dt_home_get_logout_url' ) ) {
@@ -229,7 +229,8 @@ public function footer_javascript() {
229229
'root' => esc_url_raw( rest_url() ),
230230
'nonce' => wp_create_nonce( 'wp_rest' ),
231231
'parts' => $this->parts,
232-
'user_id' => get_current_user_id(),
232+
'user_id' => DT_Magic_URL::get_current_user_id( $this->parts ),
233+
'require_login' => function_exists( 'homescreen_require_login' ) ? homescreen_require_login() : true,
233234
'invite_enabled' => function_exists( 'homescreen_invite_users_enabled' ) ? homescreen_invite_users_enabled() : false,
234235
'translations' => [
235236
'welcome' => __( 'Welcome to your Home Screen', 'disciple_tools' ),
@@ -344,18 +345,25 @@ private function show_launcher_wrapper() {
344345
$target_app_url = $this->get_target_app_url();
345346
error_log( 'DT Home: Showing launcher wrapper for URL: ' . $target_app_url );
346347

348+
// Get Magic URL for the target app so we can use the parts to determine the user ID
349+
$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
350+
$url_parts = explode( '/', $request_uri );
351+
352+
$target_magic_url = new DT_Magic_URL( $url_parts[1] );
353+
$parts = $target_magic_url->parse_url_parts();
354+
$target_magic_url->determine_post_id( $parts );
355+
356+
// Get user ID based on magic link parts
357+
$user_id = DT_Magic_URL::get_current_user_id( $parts );
358+
347359
// Get all apps for the apps selector
348360
$apps_manager = DT_Home_Apps::instance();
349-
$apps = $apps_manager->get_apps_for_user( get_current_user_id() );
350-
351-
// Output complete HTML page
352-
$target_app_url = $this->get_target_app_url();
361+
$apps = $apps_manager->get_apps_for_user( $user_id );
353362

354363
// Include wrapper template
355364
$wrapper_path = get_template_directory() . '/dt-apps/dt-home/frontend/partials/launcher-wrapper.php';
356365
if ( file_exists( $wrapper_path ) ) {
357-
// Set variables for template
358-
$target_app_url = $this->get_target_app_url();
366+
// Template has access to variables declared above
359367
include $wrapper_path;
360368
die(); // Stop all further processing
361369
} else {
@@ -494,7 +502,7 @@ public function endpoint_get( WP_REST_Request $request ) {
494502

495503
// Sanitize and fetch user id
496504
$params = dt_recursive_sanitize_array( $params );
497-
$user_id = $params['parts']['post_id'];
505+
$user_id = (int) $params['parts']['post_id'];
498506
$action = $params['action'];
499507

500508
// Handle different actions

dt-reports/magic-url-base.php

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,10 @@ public function __construct() {
4646
if ( $this->type !== $this->parts['type'] ){
4747
return;
4848
}
49-
if ( !empty( $this->parts['public_key'] ) ){
50-
if ( $this->parts['post_type'] === 'user' ){
51-
// if user
52-
$user_id = $this->magic->get_user_id( $this->parts['meta_key'], $this->parts['public_key'] );
53-
if ( ! $user_id ){ // fail if no post id for public key
54-
$this->magic->redirect_to_expired_landing_page();
55-
} else {
56-
$this->parts['post_id'] = $user_id;
57-
}
58-
} else {
59-
// get post_id
60-
$post_id = $this->magic->get_post_id( $this->parts['meta_key'], $this->parts['public_key'] );
61-
if ( ! $post_id ){ // fail if no post id for public key
62-
$this->magic->redirect_to_expired_landing_page();
63-
} else {
64-
$this->parts['post_id'] = $post_id;
65-
}
66-
}
49+
50+
$this->magic->determine_post_id( $this->parts );
51+
if ( empty( $this->parts['post_id'] ) ){
52+
$this->magic->redirect_to_expired_landing_page();
6753
}
6854

6955

dt-reports/magic-url-class.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,29 @@ public function verify_rest_endpoint_permissions_on_post( WP_REST_Request $reque
377377
return $return_parts ? $parts : true;
378378
}
379379

380+
/**
381+
* Determine the post ID based on the magic URL parts.
382+
* @param array $parts The magic URL parts.
383+
* @return void
384+
*/
385+
public function determine_post_id( &$parts ) {
386+
if ( !empty( $parts['public_key'] ) ){
387+
if ( $parts['post_type'] === 'user' ){
388+
// if user
389+
$user_id = $this->get_user_id( $parts['meta_key'], $parts['public_key'] );
390+
if ( $user_id ) {
391+
$parts['post_id'] = $user_id;
392+
}
393+
} else {
394+
// get post_id
395+
$post_id = $this->get_post_id( $parts['meta_key'], $parts['public_key'] );
396+
if ( $post_id ) {
397+
$parts['post_id'] = $post_id;
398+
}
399+
}
400+
}
401+
}
402+
380403
public function get_post_id( string $meta_key, string $public_key ){
381404
global $wpdb;
382405
$result = $wpdb->get_var( $wpdb->prepare( "
@@ -406,6 +429,29 @@ public function get_user_id( string $meta_key, string $public_key ){
406429
return false;
407430
}
408431

432+
/**
433+
* Get the current user ID from the magic link parts or the currently logged-in user
434+
* @param $parts string[] Links parts with post_id and post_type set
435+
* @return int
436+
*/
437+
public static function get_current_user_id( array $parts ) {
438+
$user_id = get_current_user_id();
439+
440+
if ( isset( $parts['post_id'], $parts['post_type'] ) ) {
441+
$post_id = $parts['post_id'];
442+
$post_type = $parts['post_type'];
443+
if ( $post_type === 'user' && !empty( $post_id ) ) {
444+
$user_id = (int) $post_id;
445+
} else if ( $post_type === 'contacts' && !empty( $post_id ) ) {
446+
$contact_user_id = Disciple_Tools_Users::get_user_for_contact( $post_id );
447+
if ( !empty( $contact_user_id ) && !is_wp_error( $contact_user_id ) ) {
448+
$user_id = (int) $contact_user_id;
449+
}
450+
}
451+
}
452+
return $user_id;
453+
}
454+
409455
public function is_valid_base_url( string $type ) {
410456
$parts = self::parse_url_parts();
411457
if ( empty( $parts ) ){ // fail if not prayer url

0 commit comments

Comments
 (0)