Plugin Directory

Changeset 3769801


Ignore:
Timestamp:
10/28/2026 03:02:56 AM (4 days ago)
Author:
heymehedi
Message:

Update to version 1.18.0 from GitHub

Location:
login-me-now
Files:
2 added
2 deleted
26 edited
1 copied

Legend:

Unmodified
Added
Removed
  • login-me-now/tags/1.18.0/app/Admin/Admin.php

    r3396479 r3769801  
    88namespace LoginMeNow\Admin;
    99
    10 use LoginMeNow\Admin\Notices\BlackFridayNotice;
    11 
    1210class Admin {
    1311        public function __construct() {
    … …  
    1816                ( new Settings() );
    1917                ( new UserProfile() );
    20                 ( new BlackFridayNotice() );
     18                ( new Promotions() );
    2119
    2220                add_filter( 'admin_footer_text', [$this, 'admin_footer_link'], 99 );
  • login-me-now/tags/1.18.0/app/Admin/Enqueuer.php

    r3290220 r3769801  
    9393                        'plugin_activated_text'  => __( 'Activated', 'login-me-now' ),
    9494                        'plugin_activate_text'   => __( 'Activate', 'login-me-now' ),
    95                         'upgrade_notice'         => true,
    9695                        'time_zone'              => wp_timezone_string(),
    9796                ];
  • login-me-now/tags/1.18.0/app/Admin/Settings.php

    r3384718 r3769801  
    6363                $fields[] = [
    6464                        'title'         => 'Enter your license key',
    65                         'description'   => "An active license key is needed to unlock all the pro features and receive automatic plugin updates. Don't have a license key? <a href='https://pluginly.com/login-me-now-pro/' target='_blank'>Get it here</a>",
     65                        'description'   => "An active license key is needed to unlock all the pro features and receive automatic plugin updates. Don't have a license key? <a href='https://loginmenow.com/pricing/' target='_blank'>Get it here</a>",
    6666                        'id'            => 'lmn_pro_lic',
    6767                        'previous_data' => SettingsRepository::get( 'lmn_pro_lic', '' ),
  • login-me-now/tags/1.18.0/app/Common/RouteBase.php

    r3147204 r3769801  
    88namespace LoginMeNow\Common;
    99
    10 use LoginMeNow\Utils\Config;
    1110use LoginMeNow\Utils\Response;
    1211use WP_Error;
    … …  
    2928                $this->request = $request;
    3029
    31                 if ( 'development' === Config::get( 'environment' ) ) {
    32                         return true;
    33                 }
    34 
    35                 if ( is_user_logged_in() && current_user_can( 'edit_posts' ) ) {
     30                if ( is_user_logged_in() && current_user_can( LOGIN_ME_NOW_MENU_CAPABILITY ) ) {
    3631                        return true;
    3732                }
  • login-me-now/tags/1.18.0/app/Controllers/SettingsController.php

    r3272204 r3769801  
    33 * @author  Pluginly
    44 * @since       1.8
    5  * @version 1.8
     5 * @version 1.17.1
    66 */
    77
    … …  
    99
    1010use LoginMeNow\Repositories\SettingsRepository;
     11use LoginMeNow\Utils\Helper;
    1112use WP_REST_Request;
    1213
    … …  
    1415        public function save( WP_REST_Request $request ) {
    1516
    16                 $params = $request->get_params();
     17                $params = $request->get_json_params();
     18                if ( empty( $params ) ) {
     19                        $params = $request->get_body_params();
     20                }
    1721
    1822                try {
    … …  
    2125                        }
    2226
     27                        $fields = $this->get_savable_fields();
     28                        $saved  = [];
     29
    2330                        foreach ( $params as $key => $value ) {
     31                                if ( ! is_string( $key ) || ! isset( $fields[$key] ) ) {
     32                                        continue;
     33                                }
     34
     35                                $value = $this->sanitize( $key, $value, $fields[$key] );
     36
    2437                                SettingsRepository::save( $key, $value );
     38                                $saved[$key] = $value;
    2539                        }
    2640
    2741                        wp_send_json_success( [
    2842                                'message' => __( 'Successfully Settings Saved', 'login-me-now' ),
    29                                 'params'  => $params,
     43                                'params'  => $saved,
    3044                        ] );
    3145
    … …  
    3448                                'message' => __( 'Settings Update Failed', 'login-me-now' ),
    3549                                'error'   => $th->getMessage(),
    36                                 'params'  => $params,
    3750                        ] );
    3851                }
    3952        }
     53
     54        /**
     55         * Fields registered through `login_me_now_settings_fields`, keyed by id.
     56         */
     57        private function get_savable_fields(): array {
     58                $fields = [];
     59
     60                foreach ( SettingsRepository::init()->get_fields() as $field ) {
     61                        if ( empty( $field['id'] ) || in_array( $field['type'] ?? '', ['separator', 'message'], true ) ) {
     62                                continue;
     63                        }
     64
     65                        $fields[$field['id']] = $field;
     66                }
     67
     68                return $fields;
     69        }
     70
     71        private function sanitize( string $key, $value, array $field ) {
     72                if ( null === $value ) {
     73                        return null;
     74                }
     75
     76                if ( '_default_user_role' === substr( $key, -strlen( '_default_user_role' ) ) ) {
     77                        $role = sanitize_key( is_string( $value ) ? $value : '' );
     78
     79                        return Helper::is_assignable_user_role( $role ) ? $role : '';
     80                }
     81
     82                switch ( $field['type'] ?? 'text' ) {
     83                        case 'switch':
     84                                return rest_sanitize_boolean( $value );
     85
     86                        case 'number':
     87                                return is_numeric( $value ) ? $value + 0 : 0;
     88
     89                        case 'multi-select':
     90                                if ( ! is_array( $value ) ) {
     91                                        return is_scalar( $value ) ? sanitize_text_field( (string) $value ) : [];
     92                                }
     93
     94                                return array_values(
     95                                        array_map(
     96                                                static fn( $item ) => is_int( $item ) ? $item : sanitize_text_field( (string) $item ),
     97                                                array_filter( $value, 'is_scalar' )
     98                                        )
     99                                );
     100
     101                        case 'textarea':
     102                                return is_scalar( $value ) ? sanitize_textarea_field( (string) $value ) : '';
     103
     104                        case 'email':
     105                                return is_scalar( $value ) ? sanitize_email( (string) $value ) : '';
     106
     107                        case 'color':
     108                                return is_scalar( $value ) ? (string) sanitize_hex_color( (string) $value ) : '';
     109
     110                        case 'file':
     111                                return is_scalar( $value ) ? esc_url_raw( (string) $value ) : '';
     112
     113                        default:
     114                                return is_scalar( $value ) ? sanitize_text_field( (string) $value ) : '';
     115                }
     116        }
    40117}
  • login-me-now/tags/1.18.0/app/Logins/FacebookLogin/Settings.php

    r3384718 r3769801  
    2020                $roles_options = [];
    2121
    22                 foreach ( Helper::get_user_roles() as $key => $role ) {
     22                foreach ( Helper::get_assignable_user_roles() as $key => $role ) {
    2323                        $roles_options[] = [
    2424                                'value' => $key,
  • login-me-now/tags/1.18.0/app/Logins/GoogleLogin/Settings.php

    r3384718 r3769801  
    2929                $roles_options = [];
    3030
    31                 foreach ( Helper::get_user_roles() as $key => $role ) {
     31                foreach ( Helper::get_assignable_user_roles() as $key => $role ) {
    3232
    3333                        $roles_options[] = [
  • login-me-now/tags/1.18.0/app/Utils/Helper.php

    r3147204 r3769801  
    8282        }
    8383
     84        /**
     85         * Roles that can be auto-assigned to users who sign up through a login provider.
     86         * Roles carrying administrative capabilities are excluded.
     87         */
     88        public static function get_assignable_user_roles(): array {
     89                $roles = [];
     90
     91                foreach ( wp_roles()->get_names() as $key => $name ) {
     92                        if ( self::is_assignable_user_role( $key ) ) {
     93                                $roles[$key] = $name;
     94                        }
     95                }
     96
     97                return $roles;
     98        }
     99
     100        public static function is_assignable_user_role( string $role ): bool {
     101                $role_object = get_role( $role );
     102
     103                if ( ! $role_object ) {
     104                        return false;
     105                }
     106
     107                $restricted_caps = apply_filters(
     108                        'login_me_now_restricted_role_capabilities',
     109                        [
     110                                'manage_options',
     111                                'promote_users',
     112                                'edit_users',
     113                                'create_users',
     114                                'delete_users',
     115                                'activate_plugins',
     116                                'install_plugins',
     117                                'edit_plugins',
     118                                'manage_network',
     119                        ]
     120                );
     121
     122                foreach ( $restricted_caps as $cap ) {
     123                        if ( $role_object->has_cap( $cap ) ) {
     124                                return false;
     125                        }
     126                }
     127
     128                return true;
     129        }
     130
    84131        public static function get_pages(): array {
    85132                $return = [];
  • login-me-now/tags/1.18.0/app/Utils/User.php

    r3147204 r3769801  
    8787                $default_role = SettingsRepository::get( "{$channel}_pro_default_user_role", false );
    8888
    89                 if ( ! is_wp_error( $user_id ) && $default_role ) {
     89                if ( ! is_wp_error( $user_id ) && $default_role && Helper::is_assignable_user_role( (string) $default_role ) ) {
    9090                        $user = new WP_User( $user_id );
    9191                        $user->remove_role( 'subscriber' );
  • login-me-now/tags/1.18.0/config.php

    r3673390 r3769801  
    22
    33return [
    4         'version'         => '1.17',
     4        'version'         => '1.18.0',
    55        'min_php'         => '7.4',
    66        'db_version'      => '1.0.0',
  • login-me-now/tags/1.18.0/login-me-now.php

    r3673390 r3769801  
    55 * Author: LoginMeNow.com
    66 * Author URI: https://loginmenow.com/
    7  * Version: 1.17
     7 * Version: 1.18.0
    88 * Tested up to: 7.1
    99 * Requires PHP: 7.4
  • login-me-now/tags/1.18.0/readme.txt

    r3673390 r3769801  
    55Tested up to: 7.1
    66Requires PHP: 7.4
    7 Stable tag: 1.17
     7Stable tag: 1.18.0
    88License: GPLv3 or any later version
    99
    … …  
    161161== Upgrade Notice ==
    162162
     163= 1.18.0 =
     164Security release. Please update as soon as possible. Restricts the settings REST API to administrators and prevents social-login users from being assigned an administrative role.
     165
    163166= 1.17 =
    164167Security release. Please update as soon as possible. Browser-extension tokens are re-issued after updating, so extension users may need to reconnect once.
    165168
    166169== Changelog ==
     170
     171= 1.18.0 – Oct 27, 2026 =
     172* Security: Admin settings REST endpoints now require the `manage_options` capability (previously any user who could edit posts, e.g. Contributors, could read and change plugin settings).
     173* Security: Settings are saved only for registered fields and are sanitized by field type.
     174* Security: The default role for users who sign up via social login can no longer be a role with administrative capabilities.
     175* Add: Dismissible Black Friday / Cyber Monday 2026 notices for administrators, shown only on the campaign dates and never in the block editor or when Pro is active.
     176* Add: `login_me_now_promotions`, `login_me_now_show_promotions` and `login_me_now_is_premium` filters.
     177* Remove: The old New Year promotional notice and an unused `upgrade_notice` setting.
     178* Fix: The license tab's "Get it here" link now points to the Login Me Now store.
    167179
    168180= 1.17 – Aug 29, 2026 =
  • login-me-now/tags/1.18.0/vendor/composer/installed.php

    r3673390 r3769801  
    22    'root' => array(
    33        'name' => 'pluginly/login-me-now',
    4         'pretty_version' => 'v1.17',
    5         'version' => '1.17.0.0',
    6         'reference' => 'd990caa222b814cbc4b1d1f3b2ce388b236b0534',
     4        'pretty_version' => 'v1.18.0',
     5        'version' => '1.18.0.0',
     6        'reference' => '5a9e14d4ec14e64442c7b0a0f61f7bb084361041',
    77        'type' => 'library',
    88        'install_path' => __DIR__ . '/../../',
    … …  
    120120        ),
    121121        'pluginly/login-me-now' => array(
    122             'pretty_version' => 'v1.17',
    123             'version' => '1.17.0.0',
    124             'reference' => 'd990caa222b814cbc4b1d1f3b2ce388b236b0534',
     122            'pretty_version' => 'v1.18.0',
     123            'version' => '1.18.0.0',
     124            'reference' => '5a9e14d4ec14e64442c7b0a0f61f7bb084361041',
    125125            'type' => 'library',
    126126            'install_path' => __DIR__ . '/../../',
  • login-me-now/trunk/app/Admin/Admin.php

    r3396479 r3769801  
    88namespace LoginMeNow\Admin;
    99
    10 use LoginMeNow\Admin\Notices\BlackFridayNotice;
    11 
    1210class Admin {
    1311        public function __construct() {
    … …  
    1816                ( new Settings() );
    1917                ( new UserProfile() );
    20                 ( new BlackFridayNotice() );
     18                ( new Promotions() );
    2119
    2220                add_filter( 'admin_footer_text', [$this, 'admin_footer_link'], 99 );
  • login-me-now/trunk/app/Admin/Enqueuer.php

    r3290220 r3769801  
    9393                        'plugin_activated_text'  => __( 'Activated', 'login-me-now' ),
    9494                        'plugin_activate_text'   => __( 'Activate', 'login-me-now' ),
    95                         'upgrade_notice'         => true,
    9695                        'time_zone'              => wp_timezone_string(),
    9796                ];
  • login-me-now/trunk/app/Admin/Settings.php

    r3384718 r3769801  
    6363                $fields[] = [
    6464                        'title'         => 'Enter your license key',
    65                         'description'   => "An active license key is needed to unlock all the pro features and receive automatic plugin updates. Don't have a license key? <a href='https://pluginly.com/login-me-now-pro/' target='_blank'>Get it here</a>",
     65                        'description'   => "An active license key is needed to unlock all the pro features and receive automatic plugin updates. Don't have a license key? <a href='https://loginmenow.com/pricing/' target='_blank'>Get it here</a>",
    6666                        'id'            => 'lmn_pro_lic',
    6767                        'previous_data' => SettingsRepository::get( 'lmn_pro_lic', '' ),
  • login-me-now/trunk/app/Common/RouteBase.php

    r3147204 r3769801  
    88namespace LoginMeNow\Common;
    99
    10 use LoginMeNow\Utils\Config;
    1110use LoginMeNow\Utils\Response;
    1211use WP_Error;
    … …  
    2928                $this->request = $request;
    3029
    31                 if ( 'development' === Config::get( 'environment' ) ) {
    32                         return true;
    33                 }
    34 
    35                 if ( is_user_logged_in() && current_user_can( 'edit_posts' ) ) {
     30                if ( is_user_logged_in() && current_user_can( LOGIN_ME_NOW_MENU_CAPABILITY ) ) {
    3631                        return true;
    3732                }
  • login-me-now/trunk/app/Controllers/SettingsController.php

    r3272204 r3769801  
    33 * @author  Pluginly
    44 * @since       1.8
    5  * @version 1.8
     5 * @version 1.17.1
    66 */
    77
    … …  
    99
    1010use LoginMeNow\Repositories\SettingsRepository;
     11use LoginMeNow\Utils\Helper;
    1112use WP_REST_Request;
    1213
    … …  
    1415        public function save( WP_REST_Request $request ) {
    1516
    16                 $params = $request->get_params();
     17                $params = $request->get_json_params();
     18                if ( empty( $params ) ) {
     19                        $params = $request->get_body_params();
     20                }
    1721
    1822                try {
    … …  
    2125                        }
    2226
     27                        $fields = $this->get_savable_fields();
     28                        $saved  = [];
     29
    2330                        foreach ( $params as $key => $value ) {
     31                                if ( ! is_string( $key ) || ! isset( $fields[$key] ) ) {
     32                                        continue;
     33                                }
     34
     35                                $value = $this->sanitize( $key, $value, $fields[$key] );
     36
    2437                                SettingsRepository::save( $key, $value );
     38                                $saved[$key] = $value;
    2539                        }
    2640
    2741                        wp_send_json_success( [
    2842                                'message' => __( 'Successfully Settings Saved', 'login-me-now' ),
    29                                 'params'  => $params,
     43                                'params'  => $saved,
    3044                        ] );
    3145
    … …  
    3448                                'message' => __( 'Settings Update Failed', 'login-me-now' ),
    3549                                'error'   => $th->getMessage(),
    36                                 'params'  => $params,
    3750                        ] );
    3851                }
    3952        }
     53
     54        /**
     55         * Fields registered through `login_me_now_settings_fields`, keyed by id.
     56         */
     57        private function get_savable_fields(): array {
     58                $fields = [];
     59
     60                foreach ( SettingsRepository::init()->get_fields() as $field ) {
     61                        if ( empty( $field['id'] ) || in_array( $field['type'] ?? '', ['separator', 'message'], true ) ) {
     62                                continue;
     63                        }
     64
     65                        $fields[$field['id']] = $field;
     66                }
     67
     68                return $fields;
     69        }
     70
     71        private function sanitize( string $key, $value, array $field ) {
     72                if ( null === $value ) {
     73                        return null;
     74                }
     75
     76                if ( '_default_user_role' === substr( $key, -strlen( '_default_user_role' ) ) ) {
     77                        $role = sanitize_key( is_string( $value ) ? $value : '' );
     78
     79                        return Helper::is_assignable_user_role( $role ) ? $role : '';
     80                }
     81
     82                switch ( $field['type'] ?? 'text' ) {
     83                        case 'switch':
     84                                return rest_sanitize_boolean( $value );
     85
     86                        case 'number':
     87                                return is_numeric( $value ) ? $value + 0 : 0;
     88
     89                        case 'multi-select':
     90                                if ( ! is_array( $value ) ) {
     91                                        return is_scalar( $value ) ? sanitize_text_field( (string) $value ) : [];
     92                                }
     93
     94                                return array_values(
     95                                        array_map(
     96                                                static fn( $item ) => is_int( $item ) ? $item : sanitize_text_field( (string) $item ),
     97                                                array_filter( $value, 'is_scalar' )
     98                                        )
     99                                );
     100
     101                        case 'textarea':
     102                                return is_scalar( $value ) ? sanitize_textarea_field( (string) $value ) : '';
     103
     104                        case 'email':
     105                                return is_scalar( $value ) ? sanitize_email( (string) $value ) : '';
     106
     107                        case 'color':
     108                                return is_scalar( $value ) ? (string) sanitize_hex_color( (string) $value ) : '';
     109
     110                        case 'file':
     111                                return is_scalar( $value ) ? esc_url_raw( (string) $value ) : '';
     112
     113                        default:
     114                                return is_scalar( $value ) ? sanitize_text_field( (string) $value ) : '';
     115                }
     116        }
    40117}
  • login-me-now/trunk/app/Logins/FacebookLogin/Settings.php

    r3384718 r3769801  
    2020                $roles_options = [];
    2121
    22                 foreach ( Helper::get_user_roles() as $key => $role ) {
     22                foreach ( Helper::get_assignable_user_roles() as $key => $role ) {
    2323                        $roles_options[] = [
    2424                                'value' => $key,
  • login-me-now/trunk/app/Logins/GoogleLogin/Settings.php

    r3384718 r3769801  
    2929                $roles_options = [];
    3030
    31                 foreach ( Helper::get_user_roles() as $key => $role ) {
     31                foreach ( Helper::get_assignable_user_roles() as $key => $role ) {
    3232
    3333                        $roles_options[] = [
  • login-me-now/trunk/app/Utils/Helper.php

    r3147204 r3769801  
    8282        }
    8383
     84        /**
     85         * Roles that can be auto-assigned to users who sign up through a login provider.
     86         * Roles carrying administrative capabilities are excluded.
     87         */
     88        public static function get_assignable_user_roles(): array {
     89                $roles = [];
     90
     91                foreach ( wp_roles()->get_names() as $key => $name ) {
     92                        if ( self::is_assignable_user_role( $key ) ) {
     93                                $roles[$key] = $name;
     94                        }
     95                }
     96
     97                return $roles;
     98        }
     99
     100        public static function is_assignable_user_role( string $role ): bool {
     101                $role_object = get_role( $role );
     102
     103                if ( ! $role_object ) {
     104                        return false;
     105                }
     106
     107                $restricted_caps = apply_filters(
     108                        'login_me_now_restricted_role_capabilities',
     109                        [
     110                                'manage_options',
     111                                'promote_users',
     112                                'edit_users',
     113                                'create_users',
     114                                'delete_users',
     115                                'activate_plugins',
     116                                'install_plugins',
     117                                'edit_plugins',
     118                                'manage_network',
     119                        ]
     120                );
     121
     122                foreach ( $restricted_caps as $cap ) {
     123                        if ( $role_object->has_cap( $cap ) ) {
     124                                return false;
     125                        }
     126                }
     127
     128                return true;
     129        }
     130
    84131        public static function get_pages(): array {
    85132                $return = [];
  • login-me-now/trunk/app/Utils/User.php

    r3147204 r3769801  
    8787                $default_role = SettingsRepository::get( "{$channel}_pro_default_user_role", false );
    8888
    89                 if ( ! is_wp_error( $user_id ) && $default_role ) {
     89                if ( ! is_wp_error( $user_id ) && $default_role && Helper::is_assignable_user_role( (string) $default_role ) ) {
    9090                        $user = new WP_User( $user_id );
    9191                        $user->remove_role( 'subscriber' );
  • login-me-now/trunk/config.php

    r3673390 r3769801  
    22
    33return [
    4         'version'         => '1.17',
     4        'version'         => '1.18.0',
    55        'min_php'         => '7.4',
    66        'db_version'      => '1.0.0',
  • login-me-now/trunk/login-me-now.php

    r3673390 r3769801  
    55 * Author: LoginMeNow.com
    66 * Author URI: https://loginmenow.com/
    7  * Version: 1.17
     7 * Version: 1.18.0
    88 * Tested up to: 7.1
    99 * Requires PHP: 7.4
  • login-me-now/trunk/readme.txt

    r3673390 r3769801  
    55Tested up to: 7.1
    66Requires PHP: 7.4
    7 Stable tag: 1.17
     7Stable tag: 1.18.0
    88License: GPLv3 or any later version
    99
    … …  
    161161== Upgrade Notice ==
    162162
     163= 1.18.0 =
     164Security release. Please update as soon as possible. Restricts the settings REST API to administrators and prevents social-login users from being assigned an administrative role.
     165
    163166= 1.17 =
    164167Security release. Please update as soon as possible. Browser-extension tokens are re-issued after updating, so extension users may need to reconnect once.
    165168
    166169== Changelog ==
     170
     171= 1.18.0 – Oct 27, 2026 =
     172* Security: Admin settings REST endpoints now require the `manage_options` capability (previously any user who could edit posts, e.g. Contributors, could read and change plugin settings).
     173* Security: Settings are saved only for registered fields and are sanitized by field type.
     174* Security: The default role for users who sign up via social login can no longer be a role with administrative capabilities.
     175* Add: Dismissible Black Friday / Cyber Monday 2026 notices for administrators, shown only on the campaign dates and never in the block editor or when Pro is active.
     176* Add: `login_me_now_promotions`, `login_me_now_show_promotions` and `login_me_now_is_premium` filters.
     177* Remove: The old New Year promotional notice and an unused `upgrade_notice` setting.
     178* Fix: The license tab's "Get it here" link now points to the Login Me Now store.
    167179
    168180= 1.17 – Aug 29, 2026 =
  • login-me-now/trunk/vendor/composer/installed.php

    r3673390 r3769801  
    22    'root' => array(
    33        'name' => 'pluginly/login-me-now',
    4         'pretty_version' => 'v1.17',
    5         'version' => '1.17.0.0',
    6         'reference' => 'd990caa222b814cbc4b1d1f3b2ce388b236b0534',
     4        'pretty_version' => 'v1.18.0',
     5        'version' => '1.18.0.0',
     6        'reference' => '5a9e14d4ec14e64442c7b0a0f61f7bb084361041',
    77        'type' => 'library',
    88        'install_path' => __DIR__ . '/../../',
    … …  
    120120        ),
    121121        'pluginly/login-me-now' => array(
    122             'pretty_version' => 'v1.17',
    123             'version' => '1.17.0.0',
    124             'reference' => 'd990caa222b814cbc4b1d1f3b2ce388b236b0534',
     122            'pretty_version' => 'v1.18.0',
     123            'version' => '1.18.0.0',
     124            'reference' => '5a9e14d4ec14e64442c7b0a0f61f7bb084361041',
    125125            'type' => 'library',
    126126            'install_path' => __DIR__ . '/../../',
Note: See TracChangeset for help on using the changeset viewer.