Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.50% covered (success)
97.50%
39 / 40
83.33% covered (success)
83.33%
5 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Authenticator
97.50% covered (success)
97.50%
39 / 40
83.33% covered (success)
83.33%
5 / 6
15
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 authenticate
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 register
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
6
 set_auth_cookies
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 maybe_create_username
85.71% covered (success)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
3.03
 can_register_with_email
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Authenticator class.
4 *
5 * This will authenticate the user. Also responsible for registration
6 * in case it is enabled in the settings.
7 *
8 * @package RtCamp\GoogleLogin
9 * @since 1.1.1
10 */
11
12declare(strict_types=1);
13
14namespace RtCamp\GoogleLogin\Utils;
15
16use WP_User;
17use stdClass;
18use Exception;
19use Throwable;
20use InvalidArgumentException;
21use RtCamp\GoogleLogin\Modules\Settings;
22
23/**
24 * Class Authenticator
25 *
26 * @package RtCamp\GoogleLogin\Utils
27 */
28class Authenticator {
29    /**
30     * Settings instance.
31     *
32     * @var Settings
33     */
34    private $settings;
35
36    /**
37     * Authenticator constructor.
38     *
39     * @param Settings $settings Settings instance.
40     */
41    public function __construct( Settings $settings ) {
42        $this->settings = $settings;
43    }
44
45    /**
46     * Authenticate the user.
47     *
48     * If registration setting is on, user will be created if
49     * that user does not exist in the application.
50     *
51     * @param stdClass $user User data object returned by Google.
52     *
53     * @return WP_User
54     * @throws InvalidArgumentException For invalid registrations.
55     */
56    public function authenticate( stdClass $user ): WP_User {
57        if ( ! property_exists( $user, 'email' ) ) {
58            throw new InvalidArgumentException( __( 'Email needs to be present for the user.', 'login-with-google' ) );
59        }
60
61        if ( email_exists( $user->email ) ) {
62            $user_wp = get_user_by( 'email', $user->email );
63
64            /**
65             * Fires once the user has been authenticated.
66             *
67             * @since 1.3.0
68             *
69             * @param WP_User $user_wp WP User data object.
70             * @param stdClass $user User data object returned by Google.
71             */
72            do_action( 'rtcamp.google_user_logged_in', $user_wp, $user );
73
74            return $user_wp;
75        }
76
77        /**
78         * Check if we need to register the user.
79         *
80         * @param stdClass $user User object from google.
81         * @since 1.0.0
82         */
83        return apply_filters( 'rtcamp.google_register_user', $this->maybe_create_username( $user ) );
84    }
85
86    /**
87     * Register the new user if setting is on for registration.
88     *
89     * @param stdClass $user User object from google.
90     *
91     * @return WP_User|null
92     * @throws Throwable Invalid email registration.
93     * @throws Exception Registration is off.
94     */
95    public function register( stdClass $user ): ?WP_User {
96        $register = true === (bool) $this->settings->registration_enabled || (bool) get_option( 'users_can_register', false );
97
98        if ( ! $register ) {
99            throw new Exception( __( 'Registration is not allowed.', 'login-with-google' ) );
100        }
101
102        try {
103            $whitelisted_domains = $this->settings->whitelisted_domains;
104            if ( empty( $whitelisted_domains ) || $this->can_register_with_email( $user->email ) ) {
105                $uid = wp_insert_user(
106                    [
107                        'user_login' => Helper::unique_username( $user->login ),
108                        'user_pass'  => wp_generate_password( 18 ),
109                        'user_email' => $user->email,
110                        'first_name' => $user->given_name ?? '',
111                        'last_name'  => $user->family_name ?? '',
112                    ]
113                );
114
115                /**
116                 * Fires once the user has been registered successfully.
117                 */
118                do_action( 'rtcamp.google_user_created', $uid, $user );
119
120                return get_user_by( 'id', $uid );
121            }
122
123            /* translators: %s is replaced with email ID of user trying to register */
124            throw new Exception( sprintf( __( 'Cannot register with this email: %s', 'login-with-google' ), $user->email ) );
125
126        } catch ( Throwable $e ) {
127
128            throw $e;
129        }
130
131    }
132
133    /**
134     * Set auth cookies for WordPress login.
135     *
136     * @param WP_User $user WP User object.
137     *
138     * @return void
139     */
140    public function set_auth_cookies( WP_User $user ) {
141        wp_clear_auth_cookie();
142        wp_set_current_user( $user->ID, $user->user_login );
143        wp_set_auth_cookie( $user->ID );
144    }
145
146    /**
147     * Assign the `login` property to user object
148     * if it doesn't exists.
149     *
150     * @param stdClass $user User object.
151     *
152     * @return stdClass
153     */
154    private function maybe_create_username( stdClass $user ): stdClass {
155        if ( property_exists( $user, 'login' ) || ! property_exists( $user, 'email' ) ) {
156            return $user;
157        }
158
159        $email       = $user->email;
160        $user_login  = sanitize_user( current( explode( '@', $email ) ), true );
161        $user_login  = Helper::unique_username( $user_login );
162        $user->login = $user_login;
163
164        return $user;
165    }
166
167    /**
168     * Check if given email can be used for registration.
169     *
170     * @param string $email Email ID.
171     *
172     * @return bool
173     */
174    private function can_register_with_email( string $email ): bool {
175        $whitelisted_domains = explode( ',', $this->settings->whitelisted_domains );
176        $whitelisted_domains = array_map( 'strtolower', $whitelisted_domains );
177        $whitelisted_domains = array_map( 'trim', $whitelisted_domains );
178        $email_parts         = explode( '@', $email );
179        $email_parts         = array_map( 'strtolower', $email_parts );
180
181        return in_array( $email_parts[1], $whitelisted_domains, true );
182    }
183}