PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 2.0.2
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v2.0.2
3.7.5 3.7.4 3.7.3 3.7.2 1-final 3.7.1 3.7.0 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.10 All 111 releases
← All changes | includes/API/Login.php +130 -293 3.7.42.0.2 View file →
@@ -6,339 +6,176 @@
6 6 use Templately\Utils\Helper;
7 7 use Templately\Utils\Options;
8 8
9 9 class Login extends API {
10 - public function permission_check( WP_REST_Request $request ) {
10 + public function permission_check( WP_REST_Request $request ) {
11 11 $this->request = $request;
12 - $_route = $request->get_route();
13 - if ( '/templately/v1/login' === $_route ) {
14 - return true;
15 - }
12 + return true;
13 + }
16 14
17 - if ( '/templately/v1/pricing' === $_route ) {
18 - return true;
19 - }
15 + public function register_routes() {
16 + $this->post( 'login', [ $this, 'login' ] );
17 + $this->post( 'logout', [ $this, 'logout' ] );
18 + $this->get( 'is-signed', [ $this, 'is_signed' ] );
19 + }
20 20
21 - if ( '/templately/v1/google-auth-url' === $_route ) {
22 - return true;
23 - }
21 + public function login(){
22 + $errors = [];
23 + $_ip = Helper::get_ip();
24 + $_site_url = home_url( '/' );
24 25
25 - return parent::permission_check( $request );
26 - }
26 + $global_signin = (bool) $this->get_param( 'global_signin', false );
27 + $viaAPI = (bool) $this->get_param( 'viaAPI', false );
28 + $email = $this->get_param( 'email', '', 'sanitize_email' );
29 + $password = $this->get_param( 'password' );
27 30
28 - public function register_routes() {
29 - $this->post( 'login', [$this, 'login'] );
30 - $this->post( 'logout', [$this, 'logout'] );
31 - $this->get( 'is-signed', [$this, 'is_signed'] );
32 - $this->get( 'pricing', [$this, 'pricing'] );
33 - $this->get( 'google-auth-url', [$this, 'google_auth_url'] );
34 - }
31 + $funcArgs = [
32 + 'ip' => $_ip,
33 + 'site_url' => $_site_url,
34 + ];
35 35
36 - public function google_auth_url() {
37 - // Get redirect_to parameter from request if provided
38 - $redirect_to = $this->get_param( 'redirect-to', '' );
36 + if( $viaAPI ) {
37 + $api_key = $this->get_param( 'api_key' );
38 + $funcArgs['api_key'] = $api_key;
39 39
40 - // Use client-provided current_url instead of HTTP_REFERER for reliability
41 - $current_url = $this->get_param( 'current_url', '' );
40 + if ( empty( $api_key ) ) {
41 + $errors['api_key'] = __( 'API Key field cannot be empty.', 'templately' );
42 + }
43 + } else {
44 + $funcArgs['email'] = $email;
45 + $funcArgs['password'] = $password;
42 46
43 - $url = $this->http()->google_auth_url( $redirect_to, $current_url );
44 - return [
45 - 'status' => 'success',
46 - 'url' => $url
47 - ];
48 - }
47 + if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
48 + $errors['email'] = __( 'Make sure you have given a valid email address.', 'templately' );
49 + }
49 50
50 - public function pricing(){
51 - $data = get_transient( "templately_subscriptions_v2" );
51 + if ( empty( $password ) ) {
52 + $errors['password'] = __( 'Password field cannot be empty.', 'templately' );
53 + }
54 + }
52 55
53 - if( is_array( $data ) && ! empty( $data ) ) {
54 - return $data;
56 + if( ! empty( $errors ) ) {
57 + return $this->error( 'login_error', $errors, 'login', 400 );
55 58 }
56 59
57 - // Field set drives the Subscription screen's plan comparison grid, so it
58 - // carries the per-plan limits too, not just price/sites.
59 - $query = 'id, price, name, slug, discounted_price, type, sites, coupon, my_cloud_items, pro_items, workspace, fsi_limit, ai_credit, description';
60 - $response = $this->http()->query(
61 - 'subscriptionPlans',
62 - $query
60 + $query = 'status, message, user{ id, name, first_name, last_name, display_name, email, profile_photo, joined, is_verified, api_key, plan, plan_expire_at, my_cloud{ limit, usages, last_pushed }, favourites{ id, type } }';
61 +
62 + $response = $this->http()->mutation(
63 + $viaAPI ? 'connectWithApiKey' : 'connect',
64 + $query,
65 + $funcArgs
63 66 )->post();
64 67
65 - set_transient( "templately_subscriptions_v2", $response, WEEK_IN_SECONDS );
68 + if( is_wp_error( $response ) ) {
69 + return $response;
70 + }
66 71
67 - return $response;
68 - }
72 + if ( $global_signin && ! Login::is_globally_signed() ) {
73 + Options::set_global_login();
74 + }
69 75
70 - public function login() {
71 - $errors = [];
72 - $_ip = Helper::get_ip();
73 - $_site_url = home_url( '/' );
76 + if ( ! empty( $response['user']['api_key'] ) ) {
77 + $this->utils('options')->set( 'api_key', $response['user']['api_key'] );
78 + unset( $response['user']['api_key'] );
79 + }
74 80
75 - $global_signin = (bool) $this->get_param( 'global_signin', false );
76 - $viaAPI = (bool) $this->get_param( 'viaAPI', false );
77 - $email = $this->get_param( 'email', '', 'sanitize_email' );
78 - $password = $this->get_param( 'password' );
81 + $meta = [
82 + 'is_globally_signed' => Login::is_globally_signed(),
83 + 'signed_as_global' => Login::signed_as_global(),
84 + ];
79 85
80 - $funcArgs = [
81 - 'ip' => $_ip,
82 - 'site_url' => $_site_url
83 - ];
86 + if( ! empty( $response['user']['my_cloud']['last_pushed'] ) ) {
87 + $_cloud_activity = unserialize( $response['user']['my_cloud']['last_pushed'] );
88 + $this->utils('options')->set( 'cloud_activity', $_cloud_activity );
89 + $meta['cloud_activity'] = $_cloud_activity;
90 + unset( $response['user']['my_cloud']['last_pushed'] );
91 + }
84 92
85 - $postArgs = [];
93 + if( ! empty( $response['user']['favourites'] ) ) {
94 + $_favourites = $this->utils('helper')->normalizeFavourites( $response['user']['favourites'] );
95 + $this->utils('options')->set('favourites', $_favourites);
86 96
87 - if ( $viaAPI ) {
88 - $api_key = $this->get_param( 'api_key' );
89 - $funcArgs['api_key'] = $api_key;
97 + unset( $response['user']['favourites'] );
98 + $meta['favourites'] = $_favourites;
99 + }
90 100
91 - if ( empty( $api_key ) ) {
92 - $errors['api_key'] = __( 'API Key field cannot be empty.', 'templately' );
93 - }
94 - } else {
95 - $funcArgs['email'] = $email;
96 - $funcArgs['password'] = addcslashes( $password, '"' );
101 + $this->utils('options')->set('user', $response['user']);
102 + $response['user']['meta'] = $this->user_meta( $meta );
97 103
98 - if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
99 - $errors['email'] = __( 'Make sure you have given a valid email address.', 'templately' );
100 - }
104 + return $response;
105 + }
101 106
102 - if ( empty( $password ) ) {
103 - $errors['password'] = __( 'Password field cannot be empty.', 'templately' );
104 - }
105 - }
107 + public function logout(){
108 + // Remove All Metas
109 + $this->utils('options')
110 + ->remove('user')
111 + ->remove('favourites')
112 + ->remove('cloud_activity')
113 + ->remove('api_key')
114 + ->remove('global_login');
106 115
107 - if ( ! empty( $errors ) ) {
108 - return $this->error( 'login_error', $errors, 'login', 400 );
109 - }
110 -
111 - // `ends_at`, `plan_type` and `cancel_at_period_end` drive the Subscription
112 - // screen's renewal line. They are asked for instead of leaning on
113 - // `plan_expire_at`, which the API resolves with `empty($subscription->ends_at)
114 - // ?? …` — a boolean that never falls through, so it never carries a date.
115 - $query = 'status, message, user{ id, name, first_name, last_name, display_name, email, profile_photo, joined, is_verified, is_company_user, is_restricted_company_user, api_key, plan, plan_expire_at, my_cloud{ limit, usages, last_pushed }, favourites{ id, type }, show_notice, reviews{ type, type_id, rating }, subscription { id, name, sites, subscription_plan_id, ends_at, plan_type, cancel_at_period_end } }';
116 -
117 - $response = $this->http()->mutation(
118 - $viaAPI ? 'connectWithApiKey' : 'connect',
119 - $query,
120 - $funcArgs
121 - )->post($postArgs);
122 -
123 - if ( is_wp_error( $response ) ) {
124 - return $response;
125 - }
126 -
127 - if ( empty( $response['user']['api_key'] ) ) {
128 - return $this->error( 'login_error', $response['message'] ?? __('Invalid API key.', 'templately'), 'login', 400 );
129 - }
130 -
131 - $options = $this->utils( 'options' );
132 - $options->use_current_user( true );
133 -
134 - try {
135 - return $this->store_connection( $response, $global_signin, $_ip, $_site_url );
136 - } finally {
137 - $options->use_current_user( false );
138 - }
139 - }
140 -
141 - /**
142 - * Persist an authenticated connection against the acting user.
143 - *
144 - * @param array $response Cloud response, already validated.
145 - * @param bool $global_signin Whether the user asked to sign in globally.
146 - * @param string $_ip Request IP, echoed back into the profile.
147 - * @param string $_site_url Site URL, echoed back into the profile.
148 - *
149 - * @return array
150 - */
151 - private function store_connection( $response, $global_signin, $_ip, $_site_url ) {
152 -
153 - if ( $global_signin && ! Login::is_globally_signed() ) {
154 - Options::set_global_login();
155 - }
156 -
157 - if ( ! empty( $response['user']['api_key'] ) ) {
158 - $this->utils( 'options' )->set( 'api_key', $response['user']['api_key'] );
159 - unset( $response['user']['api_key'] );
160 - }
161 -
162 - $meta = [
163 - 'is_globally_signed' => Login::is_globally_signed(),
164 - 'signed_as_global' => Login::signed_as_global()
165 - ];
166 -
167 - if ( ! empty( $response['user']['my_cloud']['last_pushed'] ) ) {
168 - $_cloud_activity = unserialize( $response['user']['my_cloud']['last_pushed'] );
169 - $this->utils( 'options' )->set( 'cloud_activity', $_cloud_activity );
170 - $meta['cloud_activity'] = $_cloud_activity;
171 - unset( $response['user']['my_cloud']['last_pushed'] );
172 - }
173 -
174 - if ( ! empty( $response['user']['favourites'] ) ) {
175 - $_favourites = $this->utils( 'helper' )->normalizeFavourites( $response['user']['favourites'] );
176 - $this->utils( 'options' )->set( 'favourites', $_favourites );
177 -
178 - unset( $response['user']['favourites'] );
179 - $meta['favourites'] = $_favourites;
180 - }
181 -
182 - if ( ! empty( $response['user']['reviews'] ) ) {
183 - $_reviews = $this->utils( 'helper' )->normalizeReviews( $response['user']['reviews'] );
184 - $this->utils( 'options' )->set( 'reviews', $_reviews );
185 -
186 - unset( $response['user']['reviews'] );
187 - $meta['reviews'] = $_reviews;
116 + if( $this->utils('options')->whoami() === 'global' ) {
117 + $this->utils('options')->remove_global_login();
188 118 }
189 119
190 - if(Helper::is_dev_api()){
191 - $response['user']['is_dev_api'] = true;
192 - }
120 + $global_user_id = $this->utils('options')->is_global();
121 + if( $global_user_id !== $this->utils('options')->current_user_id() ) {
122 + $global_user = $this->utils('options')->get( 'user', false, $global_user_id );
193 123
194 - if(! empty( $response['user'] ) && is_array($response['user'])){
195 - $response['user']['ip'] = $_ip;
196 - $response['user']['site_url'] = base64_encode( $_site_url );
197 - }
198 -
199 - $this->utils( 'options' )->set( 'user', $response['user'] );
200 - $response['user']['meta'] = $this->user_meta( $meta );
201 -
202 - return $response;
203 - }
204 -
205 - public function logout() {
206 - // Read the key off the acting user's own record. Options::get() falls back to
207 - // the global-login administrator when no target is given, so $this->api_key
208 - // resolves to the administrator's key for any linked user — disconnecting the
209 - // administrator's account on the cloud as well as locally.
210 - $api_key = $this->utils( 'options' )->get( 'api_key', '', get_current_user_id() );
211 -
212 - if ( empty( $api_key ) ) {
213 - return $this->error(
214 - 'logout_error',
215 - __( 'You are not connected to Templately.', 'templately' ),
216 - 'logout',
217 - 403
218 - );
219 - }
220 -
221 - $response = $this->http()->mutation(
222 - 'disconnect',
223 - 'status, message, data',
224 - [
225 - 'api_key' => $api_key,
226 - "site_url" => home_url( '/' )
227 - ]
228 - )->post();
229 -
230 - if ( is_wp_error( $response ) ) {
231 - return $response;
232 - }
233 -
234 - if ( ! isset( $response['status'] ) || $response['status'] !== 'success' ) {
235 - return $this->error( 'logout_error', $response['message'], 'logout', 404 );
236 - }
237 -
238 - // Remove All Metas
239 - $global_user = $this->delete();
240 -
241 - $response = [
242 - 'status' => 'success',
243 - 'message' => __( 'Logged out.', 'templately' )
244 - ];
245 -
246 - if ( ! empty( $global_user ) ) {
247 - $response['global_user'] = $global_user;
248 - }
249 -
250 - return $response;
251 - }
252 -
253 - public function delete(){
254 - $options = $this->utils( 'options' );
255 -
256 - // Pin the removals to the acting user. Without the pin, Options::user_id()
257 - // resolves a linked user to the global-login administrator and the delete
258 - // path wipes the administrator's connection instead of the caller's.
259 - $options->use_current_user( true );
260 -
261 - try {
262 - $options
263 - ->remove( 'user' )
264 - ->remove( 'favourites' )
265 - ->remove( 'reviews' )
266 - ->remove( 'cloud_activity' )
267 - ->remove( 'api_key' )
268 - ->remove( 'global_login' )
269 - ->remove( 'total_download_counts' )
270 - ->remove( 'templates_in_clouds' );
271 -
272 - if ( $options->who_am_i() === 'global' ) {
273 - $options->remove_global_login();
124 + if( ! empty( $global_user ) ) {
125 + $global_user['meta'] = $this->user_meta();
274 126 }
275 - } finally {
276 - $options->use_current_user( false );
277 127 }
278 128
279 - $global_user_id = $this->utils( 'options' )->is_global();
280 - $global_user = null;
129 + $response = [
130 + 'status' => 'success',
131 + 'message' => __( 'Logged out.', 'templately' ),
132 + ];
281 133
282 - if ( $global_user_id !== $this->utils( 'options' )->current_user_id() ) {
283 - $global_user = $this->utils( 'options' )->get( 'user', false, $global_user_id );
134 + if( ! empty( $global_user ) ) {
135 + $response['global_user'] = $global_user;
136 + }
284 137
285 - if ( ! empty( $global_user ) ) {
286 - if ( is_array( $global_user ) ) {
287 - unset( $global_user['api_key'] );
288 - }
289 -
290 - $global_user['meta'] = $this->user_meta();
291 - }
292 - }
293 -
294 - return $global_user;
138 + return $response;
295 139 }
296 140
297 - public static function is_signed(): array {
298 - $_response = [
299 - 'status' => 'success'
300 - ];
141 + public static function is_signed(){
142 + $_response = [
143 + 'status' => 'success'
144 + ];
301 145
302 - $_user = ( new static )->utils( 'options' )->get( 'user', null );
146 + $_user = (new static)->utils( 'options' )->get('user', null);
303 147
304 - if ( ! is_null( $_user ) ) {
305 - // Profiles stored before 3.7.1 may still carry the cloud API key.
306 - if ( is_array( $_user ) ) {
307 - unset( $_user['api_key'] );
308 - }
148 + if( ! is_null( $_user ) ) {
149 + $_user['meta'] = self::get_instance()->user_meta();
150 + }
309 151
310 - $_user['meta'] = self::get_instance()->user_meta();
311 - }
152 + if( empty( $_user ) ) {
153 + $_response['status'] = 'error';
154 + }
312 155
313 - if ( empty( $_user ) ) {
314 - $_response['status'] = 'error';
315 - }
156 + $_response['user'] = $_user;
316 157
317 - $_response['user'] = $_user;
158 + return $_response;
159 + }
318 160
319 - return $_response;
320 - }
161 + public function user_meta( $meta = [] ){
162 + $_meta = [
163 + 'link_account' => self::utils( 'options' )->link_account(),
164 + 'unlink_account' => self::utils( 'options' )->unlink_account(),
165 + 'is_globally_signed' => Login::is_globally_signed(),
166 + 'signed_as_global' => Login::signed_as_global(),
167 + 'starred' => self::utils('options')->get('favourites'),
168 + 'cloud_activity' => self::utils( 'options' )->get('cloud_activity'),
169 + 'has_api' => rest_sanitize_boolean( self::utils( 'options' )->get('api_key' ) ),
170 + ];
321 171
322 - public function user_meta( $meta = [] ): array {
323 - $_meta = [
324 - 'link_account' => self::utils( 'options' )->link_account(),
325 - 'unlink_account' => self::utils( 'options' )->unlink_account(),
326 - 'is_globally_signed' => Login::is_globally_signed(),
327 - 'signed_as_global' => Login::signed_as_global(),
328 - 'starred' => self::utils( 'options' )->get( 'favourites' ),
329 - 'reviews' => self::utils( 'options' )->get( 'reviews' ),
330 - 'cloud_activity' => self::utils( 'options' )->get( 'cloud_activity' ),
331 - 'has_api' => rest_sanitize_boolean( self::utils( 'options' )->get( 'api_key' ) )
332 - ];
172 + return array_merge( $_meta, $meta );
173 + }
333 174
334 - return array_merge( $_meta, $meta );
335 - }
336 -
337 - public static function is_globally_signed(): bool {
338 - return rest_sanitize_boolean( ( new static )->utils( 'options' )->is_globally_signed() );
339 - }
340 -
341 - public static function signed_as_global(): bool {
342 - return rest_sanitize_boolean( ( new static )->utils( 'options' )->signed_as_global() );
343 - }
344 -}
175 + public static function is_globally_signed(){
176 + return rest_sanitize_boolean( ( new static )->utils('options')->is_globally_signed() );
177 + }
178 + public static function signed_as_global(){
179 + return rest_sanitize_boolean( ( new static )->utils('options')->signed_as_global() );
180 + }
181 +}