Skip to content

Commit c6667a4

Browse files
committed
Add recaptcha.
1 parent b973fd3 commit c6667a4

16 files changed

Lines changed: 225 additions & 61 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace App\Traits;
3+
namespace App\Features;
44

55
use Roots\WPConfig\Config;
66
use function Env\env;

app/Features/Recaptcha.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace App\Features;
4+
5+
use Roots\WPConfig\Config;
6+
7+
trait Recaptcha {
8+
public static function validate_recaptcha() : void {
9+
$recaptcha_token = $_POST['token'] ?? '';
10+
$recaptcha_secret = Config::get('RECAPTCHA_SECRET');
11+
12+
if($recaptcha_secret && $recaptcha_token) {
13+
$response = wp_remote_get(add_query_arg(array(
14+
'secret' => $recaptcha_secret,
15+
'response' => $recaptcha_token,
16+
), 'https://www.google.com/recaptcha/api/siteverify'));
17+
$body = wp_remote_retrieve_body($response);
18+
$result = json_decode($body);
19+
20+
if (!$result->success || $result->score < 0.5) {
21+
wp_send_json_error(
22+
array(
23+
'success' => false,
24+
'message' => __('Incorrect email or password.', APP_THEME_LOCALE),
25+
'result' => $result,
26+
),
27+
400
28+
);
29+
}
30+
}
31+
}
32+
}

app/Hooks/Auth/Ajax.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,22 @@
22

33
namespace App\Hooks\Auth;
44

5+
use App\Features\Recaptcha;
56
use App\Hooks\Queue\Post;
67
use Ramsey\Uuid\Uuid;
78
use Roots\WPConfig\Config;
89
use Timber\Timber;
910
use function Env\env;
1011

1112
class Ajax {
13+
use Recaptcha;
1214
public static function sign_in(): void {
1315
if (!defined('DOING_AJAX') || !DOING_AJAX) {
1416
wp_send_json_error(array('message' => __('Invalid request.', APP_THEME_LOCALE)));
1517
}
1618

19+
self::validate_recaptcha();
20+
1721
$email = isset($_POST['email']) ? sanitize_email($_POST['email']) : '';
1822
$password = $_POST['password'] ?? '';
1923
$remember_me = !!$_POST['remember_me'];
@@ -22,8 +26,6 @@ public static function sign_in(): void {
2226
wp_send_json_error(array('message' => __('Email and password are required.', APP_THEME_LOCALE)));
2327
}
2428

25-
app_log('sign_in: testing');
26-
2729
$userdata = get_user_by('email', $email);
2830

2931
if (!$userdata) {
@@ -105,6 +107,8 @@ public static function sign_up(): void {
105107
]);
106108
}
107109

110+
self::validate_recaptcha();
111+
108112
$email = sanitize_email($_POST['email']);
109113

110114
if (!is_email($email)) {
@@ -203,6 +207,8 @@ public static function forgot_password(): void {
203207
]);
204208
}
205209

210+
self::validate_recaptcha();
211+
206212
$email = sanitize_email($_POST['email']);
207213

208214
if (!is_email($email)) {
@@ -280,6 +286,8 @@ public static function reset_password(): void {
280286
]);
281287
}
282288

289+
self::validate_recaptcha();
290+
283291
$key = sanitize_text_field($_POST['key']);
284292
$email = sanitize_user($_POST['email']);
285293
$password = $_POST['password'];

app/Hooks/Migrations/Cron.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace App\Hooks\Migrations;
44

5-
use App\Traits\Migrate;
5+
use App\Features\Migrate;
66

77
class Cron {
88
use Migrate;

app/Hooks/Security.php

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,78 @@
22

33
namespace App\Hooks;
44

5+
use Roots\WPConfig\Config;
6+
use Timber\Timber;
7+
58
class Security {
6-
public static function init() : void {
9+
public static function init(): void {
710
add_action('rest_api_init', self::cors_headers(...));
11+
add_action('wp_head', array(Security::class, 'add_recaptcha'));
812

913
remove_action('wp_head', 'rest_output_link_wp_head', 10);
1014
remove_action('wp_head', 'wp_oembed_add_discovery_links', 10);
1115
remove_action('template_redirect', 'rest_output_link_header', 10);
1216

13-
remove_action( 'admin_init', '_maybe_update_core' );
14-
remove_action( 'wp_version_check', 'wp_version_check' );
17+
remove_action('admin_init', '_maybe_update_core');
18+
remove_action('wp_version_check', 'wp_version_check');
1519

16-
remove_action( 'load-plugins.php', 'wp_update_plugins' );
17-
remove_action( 'load-update.php', 'wp_update_plugins' );
18-
remove_action( 'load-update-core.php', 'wp_update_plugins' );
19-
remove_action( 'admin_init', '_maybe_update_plugins' );
20-
remove_action( 'wp_update_plugins', 'wp_update_plugins' );
20+
remove_action('load-plugins.php', 'wp_update_plugins');
21+
remove_action('load-update.php', 'wp_update_plugins');
22+
remove_action('load-update-core.php', 'wp_update_plugins');
23+
remove_action('admin_init', '_maybe_update_plugins');
24+
remove_action('wp_update_plugins', 'wp_update_plugins');
2125

22-
remove_action( 'load-themes.php', 'wp_update_themes' );
23-
remove_action( 'load-update.php', 'wp_update_themes' );
24-
remove_action( 'load-update-core.php', 'wp_update_themes' );
25-
remove_action( 'admin_init', '_maybe_update_themes' );
26-
remove_action( 'wp_update_themes', 'wp_update_themes' );
26+
remove_action('load-themes.php', 'wp_update_themes');
27+
remove_action('load-update.php', 'wp_update_themes');
28+
remove_action('load-update-core.php', 'wp_update_themes');
29+
remove_action('admin_init', '_maybe_update_themes');
30+
remove_action('wp_update_themes', 'wp_update_themes');
2731

28-
remove_action( 'update_option_WPLANG', 'wp_clean_update_cache', 10, 0 );
29-
remove_action( 'wp_maybe_auto_update', 'wp_maybe_auto_update' );
30-
remove_action( 'init', 'wp_schedule_update_checks' );
31-
remove_action( 'wp_delete_temp_updater_backups', 'wp_delete_all_temp_backups' );
32-
}
32+
remove_action('update_option_WPLANG', 'wp_clean_update_cache', 10, 0);
33+
remove_action('wp_maybe_auto_update', 'wp_maybe_auto_update');
34+
remove_action('init', 'wp_schedule_update_checks');
35+
remove_action('wp_delete_temp_updater_backups', 'wp_delete_all_temp_backups');
36+
}
3337

34-
public static function cors_headers() : void {
38+
public static function cors_headers(): void {
3539
header("Access-Control-Allow-Origin: https://*.modycloud.test");
3640
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
3741
header("Access-Control-Allow-Headers: Authorization, Content-Type");
3842
header("Access-Control-Allow-Credentials: true");
3943
}
44+
45+
public static function add_recaptcha(): void {
46+
if ( is_singular() ) {
47+
global $post;
48+
$blocks = parse_blocks( $post->post_content );
49+
if( $blocks && is_array( $blocks ) ){
50+
51+
$add_script = function() {
52+
$recaptcha_site_key = Config::get('RECAPTCHA_KEY');
53+
$recaptcha_site_secret = Config::get('RECAPTCHA_SECRET');
54+
55+
if(!$recaptcha_site_key || !$recaptcha_site_secret) {
56+
return;
57+
}
58+
59+
echo Timber::compile('@app/components/tags/script.twig', [
60+
'src' => add_query_arg([
61+
'render' => $recaptcha_site_key,
62+
], 'https://www.google.com/recaptcha/api.js'),
63+
'defer' => true,
64+
]);
65+
};
66+
67+
$protected_pages = array(
68+
'app/auth'
69+
);
70+
foreach( $blocks as $block ){
71+
if( in_array($block['blockName'], $protected_pages )){
72+
$add_script();
73+
return;
74+
}
75+
}
76+
}
77+
}
78+
}
4079
}

app/Hooks/Sites/Routes.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace App\Hooks\Sites;
44

5-
use App\Traits\Migrate;
5+
use App\Features\Migrate;
66

77
class Routes {
88
use Migrate;

config/application.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,12 @@ function app_get_subdomain(): string
183183
Config::define('APP_PROTOCOL', env('APP_PROTOCOL') ?? 'http://');
184184
Config::define('APP_PATH', $root_dir . '/app');
185185
Config::define('APP_THEME_DOMAIN', 'app');
186+
Config::define('APP_MAIN_API_USER', env('APP_MAIN_API_USER'));
187+
Config::define('APP_MAIN_API_KEY', env('APP_MAIN_API_KEY'));
186188

187189
Config::define('ROOT_DIR', $webroot_dir);
188190
Config::define('SRC_PATH', $root_dir . '/resources');
191+
define('SRC_PATH', $root_dir . '/resources');
189192
Config::define('LOGS_PATH', $root_dir . '/logs');
190193

191194
Config::define('MC_SITES_PATH', __DIR__ . '/sites');
@@ -196,8 +199,6 @@ function app_get_subdomain(): string
196199
Config::define('MC_MIGRATIONS_PATH', $root_dir . '/app/migrations');
197200
Config::define('MC_PLUGINS_PATH', $webroot_dir . '/content/plugins');
198201
Config::define('MC_APP_PASSWD_NAME', 'app.passwd.mody.cloud');
199-
Config::define('APP_MAIN_API_USER', env('APP_MAIN_API_USER'));
200-
Config::define('APP_MAIN_API_KEY', env('APP_MAIN_API_KEY'));
201202

202203
Config::define('DEFAULT_DB_HOST', '127.0.0.1');
203204
Config::define('CHILD_SITE', env('CHILD_SITE') ?? false);
@@ -209,6 +210,9 @@ function app_get_subdomain(): string
209210

210211
Config::define('SPACE_NAME', env('SPACE_NAME') ?? null);
211212
Config::define('APP_CHILD_SITES_TOKEN', env('APP_CHILD_SITES_TOKEN') ?? null);
213+
214+
Config::define('RECAPTCHA_KEY', env('RECAPTCHA_KEY') ?? null);
215+
Config::define('RECAPTCHA_SECRET', env('RECAPTCHA_SECRET') ?? null);
212216
/**
213217
* Allow WordPress to detect HTTPS when used behind a reverse proxy or a load balancer
214218
* See https://codex.wordpress.org/Function_Reference/is_ssl#Notes

config/webpack.config.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
const path = require('path');
22
const defaults = require('@wordpress/scripts/config/webpack.config.js');
3+
const webpack = require('webpack')
4+
const dotenv = require('dotenv')
35

4-
module.exports = {
6+
const env = dotenv.config().parsed
7+
const envKeys = Object.keys(env).reduce((prev, next) => {
8+
prev[`process.env.${next}`] = JSON.stringify(env[next])
9+
return prev
10+
}, {})
11+
12+
module.exports = (env) => ({
513
...defaults,
614
entry: {
715
'app': path.resolve(process.cwd(), 'resources/scripts', 'app.js'),
@@ -45,5 +53,9 @@ module.exports = {
4553
},
4654
},
4755
]
48-
}
49-
};
56+
},
57+
plugins: [
58+
...defaults.plugins,
59+
new webpack.DefinePlugin(envKeys)
60+
]
61+
});

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"aos": "^2.3.4",
3333
"babel-loader": "^9.2.1",
3434
"css-loader": "^7.1.2",
35+
"dotenv": "^16.4.7",
3536
"gettext-parser": "^8.0.0",
3637
"glob": "^11.0.1",
3738
"react-router-dom": "^7.1.1",

pnpm-lock.yaml

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)