PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.7.2
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.7.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 +112 -20 3.0.33.7.2 View file →
@@ -17,8 +17,12 @@
17 17 if ( '/templately/v1/pricing' === $_route ) {
18 18 return true;
19 19 }
20 20
21 + if ( '/templately/v1/google-auth-url' === $_route ) {
22 + return true;
23 + }
24 +
21 25 return parent::permission_check( $request );
22 26 }
23 27
24 28 public function register_routes() {
@@ -25,10 +29,25 @@
25 29 $this->post( 'login', [$this, 'login'] );
26 30 $this->post( 'logout', [$this, 'logout'] );
27 31 $this->get( 'is-signed', [$this, 'is_signed'] );
28 32 $this->get( 'pricing', [$this, 'pricing'] );
33 + $this->get( 'google-auth-url', [$this, 'google_auth_url'] );
29 34 }
30 35
36 + public function google_auth_url() {
37 + // Get redirect_to parameter from request if provided
38 + $redirect_to = $this->get_param( 'redirect-to', '' );
39 +
40 + // Use client-provided current_url instead of HTTP_REFERER for reliability
41 + $current_url = $this->get_param( 'current_url', '' );
42 +
43 + $url = $this->http()->google_auth_url( $redirect_to, $current_url );
44 + return [
45 + 'status' => 'success',
46 + 'url' => $url
47 + ];
48 + }
49 +
31 50 public function pricing(){
32 51 $data = get_transient( "templately_subscriptions" );
33 52
34 53 if( is_array( $data ) && ! empty( $data ) ) {
@@ -34,9 +53,9 @@
34 53 if( is_array( $data ) && ! empty( $data ) ) {
35 54 return $data;
36 55 }
37 56
38 - $query = 'id, price, name, discounted_price, type, sites';
57 + $query = 'id, price, name, discounted_price, type, sites, coupon';
39 58 $response = $this->http()->query(
40 59 'subscriptionPlans',
41 60 $query
42 61 )->post();
@@ -60,8 +79,10 @@
60 79 'ip' => $_ip,
61 80 'site_url' => $_site_url
62 81 ];
63 82
83 + $postArgs = [];
84 +
64 85 if ( $viaAPI ) {
65 86 $api_key = $this->get_param( 'api_key' );
66 87 $funcArgs['api_key'] = $api_key;
67 88
@@ -84,20 +105,46 @@
84 105 if ( ! empty( $errors ) ) {
85 106 return $this->error( 'login_error', $errors, 'login', 400 );
86 107 }
87 108
88 - $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 }, show_notice, reviews{ type, type_id, rating } }';
109 + $query = 'status, message, user{ id, name, first_name, last_name, display_name, email, profile_photo, joined, is_verified, is_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 } }';
89 110
90 111 $response = $this->http()->mutation(
91 112 $viaAPI ? 'connectWithApiKey' : 'connect',
92 113 $query,
93 114 $funcArgs
94 - )->post();
115 + )->post($postArgs);
95 116
96 117 if ( is_wp_error( $response ) ) {
97 118 return $response;
98 119 }
99 120
121 + if ( empty( $response['user']['api_key'] ) ) {
122 + return $this->error( 'login_error', $response['message'] ?? __('Invalid API key.', 'templately'), 'login', 400 );
123 + }
124 +
125 + $options = $this->utils( 'options' );
126 + $options->use_current_user( true );
127 +
128 + try {
129 + return $this->store_connection( $response, $global_signin, $_ip, $_site_url );
130 + } finally {
131 + $options->use_current_user( false );
132 + }
133 + }
134 +
135 + /**
136 + * Persist an authenticated connection against the acting user.
137 + *
138 + * @param array $response Cloud response, already validated.
139 + * @param bool $global_signin Whether the user asked to sign in globally.
140 + * @param string $_ip Request IP, echoed back into the profile.
141 + * @param string $_site_url Site URL, echoed back into the profile.
142 + *
143 + * @return array
144 + */
145 + private function store_connection( $response, $global_signin, $_ip, $_site_url ) {
146 +
100 147 if ( $global_signin && ! Login::is_globally_signed() ) {
101 148 Options::set_global_login();
102 149 }
103 150
@@ -133,8 +180,17 @@
133 180 unset( $response['user']['reviews'] );
134 181 $meta['reviews'] = $_reviews;
135 182 }
136 183
184 + if(Helper::is_dev_api()){
185 + $response['user']['is_dev_api'] = true;
186 + }
187 +
188 + if(! empty( $response['user'] ) && is_array($response['user'])){
189 + $response['user']['ip'] = $_ip;
190 + $response['user']['site_url'] = base64_encode( $_site_url );
191 + }
192 +
137 193 $this->utils( 'options' )->set( 'user', $response['user'] );
138 194 $response['user']['meta'] = $this->user_meta( $meta );
139 195
140 196 return $response;
@@ -140,13 +196,28 @@
140 196 return $response;
141 197 }
142 198
143 199 public function logout() {
200 + // Read the key off the acting user's own record. Options::get() falls back to
201 + // the global-login administrator when no target is given, so $this->api_key
202 + // resolves to the administrator's key for any linked user — disconnecting the
203 + // administrator's account on the cloud as well as locally.
204 + $api_key = $this->utils( 'options' )->get( 'api_key', '', get_current_user_id() );
205 +
206 + if ( empty( $api_key ) ) {
207 + return $this->error(
208 + 'logout_error',
209 + __( 'You are not connected to Templately.', 'templately' ),
210 + 'logout',
211 + 403
212 + );
213 + }
214 +
144 215 $response = $this->http()->mutation(
145 216 'disconnect',
146 217 'status, message, data',
147 218 [
148 - 'api_key' => $this->api_key,
219 + 'api_key' => $api_key,
149 220 "site_url" => home_url( '/' )
150 221 ]
151 222 )->post();
152 223
@@ -173,21 +244,33 @@
173 244 return $response;
174 245 }
175 246
176 247 public function delete(){
177 - $this->utils( 'options' )
178 - ->remove( 'user' )
179 - ->remove( 'favourites' )
180 - ->remove( 'reviews' )
181 - ->remove( 'cloud_activity' )
182 - ->remove( 'api_key' )
183 - ->remove( 'global_login' )
184 - ->remove( 'templates_in_clouds' );
248 + $options = $this->utils( 'options' );
185 249
186 - if ( $this->utils( 'options' )->whoami() === 'global' ) {
187 - $this->utils( 'options' )->remove_global_login();
188 - }
250 + // Pin the removals to the acting user. Without the pin, Options::user_id()
251 + // resolves a linked user to the global-login administrator and the delete
252 + // path wipes the administrator's connection instead of the caller's.
253 + $options->use_current_user( true );
189 254
255 + try {
256 + $options
257 + ->remove( 'user' )
258 + ->remove( 'favourites' )
259 + ->remove( 'reviews' )
260 + ->remove( 'cloud_activity' )
261 + ->remove( 'api_key' )
262 + ->remove( 'global_login' )
263 + ->remove( 'total_download_counts' )
264 + ->remove( 'templates_in_clouds' );
265 +
266 + if ( $options->who_am_i() === 'global' ) {
267 + $options->remove_global_login();
268 + }
269 + } finally {
270 + $options->use_current_user( false );
271 + }
272 +
190 273 $global_user_id = $this->utils( 'options' )->is_global();
191 274 $global_user = null;
192 275
193 276 if ( $global_user_id !== $this->utils( 'options' )->current_user_id() ) {
@@ -193,8 +276,12 @@
193 276 if ( $global_user_id !== $this->utils( 'options' )->current_user_id() ) {
194 277 $global_user = $this->utils( 'options' )->get( 'user', false, $global_user_id );
195 278
196 279 if ( ! empty( $global_user ) ) {
280 + if ( is_array( $global_user ) ) {
281 + unset( $global_user['api_key'] );
282 + }
283 +
197 284 $global_user['meta'] = $this->user_meta();
198 285 }
199 286 }
200 287
@@ -200,9 +287,9 @@
200 287
201 288 return $global_user;
202 289 }
203 290
204 - public static function is_signed() {
291 + public static function is_signed(): array {
205 292 $_response = [
206 293 'status' => 'success'
207 294 ];
208 295
@@ -208,8 +295,13 @@
208 295
209 296 $_user = ( new static )->utils( 'options' )->get( 'user', null );
210 297
211 298 if ( ! is_null( $_user ) ) {
299 + // Profiles stored before 3.7.1 may still carry the cloud API key.
300 + if ( is_array( $_user ) ) {
301 + unset( $_user['api_key'] );
302 + }
303 +
212 304 $_user['meta'] = self::get_instance()->user_meta();
213 305 }
214 306
215 307 if ( empty( $_user ) ) {
@@ -220,9 +312,9 @@
220 312
221 313 return $_response;
222 314 }
223 315
224 - public function user_meta( $meta = [] ) {
316 + public function user_meta( $meta = [] ): array {
225 317 $_meta = [
226 318 'link_account' => self::utils( 'options' )->link_account(),
227 319 'unlink_account' => self::utils( 'options' )->unlink_account(),
228 320 'is_globally_signed' => Login::is_globally_signed(),
@@ -235,12 +327,12 @@
235 327
236 328 return array_merge( $_meta, $meta );
237 329 }
238 330
239 - public static function is_globally_signed() {
331 + public static function is_globally_signed(): bool {
240 332 return rest_sanitize_boolean( ( new static )->utils( 'options' )->is_globally_signed() );
241 333 }
242 334
243 - public static function signed_as_global() {
335 + public static function signed_as_global(): bool {
244 336 return rest_sanitize_boolean( ( new static )->utils( 'options' )->signed_as_global() );
245 337 }
246 -}
338 +}