diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..b3688f09 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c36ffdfc --- /dev/null +++ b/.gitignore @@ -0,0 +1,53 @@ +# Wordpress - ignore core, configuration, examples, uploads and logs. +# https://github.com/github/gitignore/blob/main/WordPress.gitignore + +# Core +# +# Note: if you want to stage/commit WP core files +# you can delete this whole section/until Configuration. +/wp-admin/ +/wp-content/index.php +/wp-content/languages +/wp-content/plugins/akismet +/wp-content/plugins/hello.php +/wp-content/plugins/index.php +/wp-content/themes/index.php +/wp-includes/ +/index.php +/license.txt +/readme.html +/wp-*.php +/xmlrpc.php + +# Configuration +wp-config.php + +# docker +docker-compose.yml + +# Example themes +/wp-content/themes/twenty*/ + +# Example plugin +/wp-content/plugins/hello.php + +# Uploads +/wp-content/uploads/ + +# Log files +*.log + +# htaccess +/.htaccess + +# All plugins +# +# Note: If you wish to whitelist plugins, +# uncomment the next line +#/wp-content/plugins + +# All themes +# +# Note: If you wish to whitelist themes, +# uncomment the next line +#/wp-content/themes \ No newline at end of file diff --git a/Apiki.postman_collection.json b/Apiki.postman_collection.json new file mode 100644 index 00000000..1cafd620 --- /dev/null +++ b/Apiki.postman_collection.json @@ -0,0 +1,123 @@ +{ + "info": { + "_postman_id": "36fe6f32-50e4-408c-bc17-a4df3359024d", + "name": "Apiki", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "38156146" + }, + "item": [ + { + "name": "Login Teste APIKI", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "// Parseia a resposta como JSON", + "var jsonData = pm.response.json();", + "", + "// Verifica se o campo \"token\" existe na resposta", + "if (jsonData.token) {", + " // Define a variável global \"auth_token\" com o valor do token", + " pm.globals.set(\"auth_token\", jsonData.token);", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"user_login\": \"mateus\",\n \"user_password\": \"$fnzFI&w%H2PtUkjnQ\"\n}" + }, + "url": { + "raw": "http://localhost:8000/wp-json/api/login", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8000", + "path": [ + "wp-json", + "api", + "login" + ] + } + }, + "response": [] + }, + { + "name": "Favoritar Post", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"post_id\": 1\n}" + }, + "url": { + "raw": "http://localhost:8000/wp-json/api/favorite", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8000", + "path": [ + "wp-json", + "api", + "favorite" + ] + } + }, + "response": [] + }, + { + "name": "Logout Teste APIKI", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"user_login\": \"mateus\",\n \"user_password\": \"$fnzFI&w%H2PtUkjnQ\"\n}" + }, + "url": { + "raw": "http://localhost:8000/wp-json/api/logoff", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8000", + "path": [ + "wp-json", + "api", + "logoff" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/wp-content/.DS_Store b/wp-content/.DS_Store new file mode 100644 index 00000000..12ae8fdd Binary files /dev/null and b/wp-content/.DS_Store differ diff --git a/wp-content/plugins/.DS_Store b/wp-content/plugins/.DS_Store new file mode 100644 index 00000000..0541ecf4 Binary files /dev/null and b/wp-content/plugins/.DS_Store differ diff --git a/wp-content/plugins/mateus-avila-isidoro.zip b/wp-content/plugins/mateus-avila-isidoro.zip new file mode 100644 index 00000000..f63c9e8d Binary files /dev/null and b/wp-content/plugins/mateus-avila-isidoro.zip differ diff --git a/wp-content/plugins/mateus-avila-isidoro/Apiki.postman_collection.json b/wp-content/plugins/mateus-avila-isidoro/Apiki.postman_collection.json new file mode 100644 index 00000000..1cafd620 --- /dev/null +++ b/wp-content/plugins/mateus-avila-isidoro/Apiki.postman_collection.json @@ -0,0 +1,123 @@ +{ + "info": { + "_postman_id": "36fe6f32-50e4-408c-bc17-a4df3359024d", + "name": "Apiki", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "38156146" + }, + "item": [ + { + "name": "Login Teste APIKI", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "// Parseia a resposta como JSON", + "var jsonData = pm.response.json();", + "", + "// Verifica se o campo \"token\" existe na resposta", + "if (jsonData.token) {", + " // Define a variável global \"auth_token\" com o valor do token", + " pm.globals.set(\"auth_token\", jsonData.token);", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"user_login\": \"mateus\",\n \"user_password\": \"$fnzFI&w%H2PtUkjnQ\"\n}" + }, + "url": { + "raw": "http://localhost:8000/wp-json/api/login", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8000", + "path": [ + "wp-json", + "api", + "login" + ] + } + }, + "response": [] + }, + { + "name": "Favoritar Post", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"post_id\": 1\n}" + }, + "url": { + "raw": "http://localhost:8000/wp-json/api/favorite", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8000", + "path": [ + "wp-json", + "api", + "favorite" + ] + } + }, + "response": [] + }, + { + "name": "Logout Teste APIKI", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"user_login\": \"mateus\",\n \"user_password\": \"$fnzFI&w%H2PtUkjnQ\"\n}" + }, + "url": { + "raw": "http://localhost:8000/wp-json/api/logoff", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8000", + "path": [ + "wp-json", + "api", + "logoff" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/wp-content/plugins/mateus-avila-isidoro/classes/install.php b/wp-content/plugins/mateus-avila-isidoro/classes/install.php new file mode 100644 index 00000000..937a5326 --- /dev/null +++ b/wp-content/plugins/mateus-avila-isidoro/classes/install.php @@ -0,0 +1,48 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link https://www.linkedin.com/in/mateusavilaisidoro + */ + +namespace MateusAvila; + +class InstallWordpressPlugin +{ + public function __construct() + { + // Usa o hook correto para ativação + register_activation_hook( MAINDIR . '/mateus-avila-isidoro.php', [ 'MateusAvila\InstallWordpressPlugin', 'create_table' ] ); + } + + /** + * Create new table when the user activates the plugin + * + * @return void apenas cria o banco + */ + public static function create_table() + { + global $wpdb; + $table = $wpdb->prefix . "favorite"; + $charset = $wpdb->get_charset_collate(); + + $sql = "CREATE TABLE IF NOT EXISTS $table ( + id BIGINT(20) NOT NULL AUTO_INCREMENT, + post_id BIGINT(20) NOT NULL, + user_id BIGINT(20) NOT NULL, + fav_date DATETIME NOT NULL, + PRIMARY KEY (id) + ) $charset;"; + + require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); + dbDelta( $sql ); + } +} + +$app = new InstallWordpressPlugin(); diff --git a/wp-content/plugins/mateus-avila-isidoro/classes/routes.php b/wp-content/plugins/mateus-avila-isidoro/classes/routes.php new file mode 100644 index 00000000..1f8bbd3c --- /dev/null +++ b/wp-content/plugins/mateus-avila-isidoro/classes/routes.php @@ -0,0 +1,254 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link https://www.linkedin.com/in/mateusavilaisidoro + */ + +namespace MateusAvila; + +class RoutesWordpressPlugin +{ + + /** + * Construtor da classe. + * + */ + public function __construct() + { + add_action('send_headers', [$this, 'allow_cors']); + $this->add_default_routes(); + } + + /** + * allow CORS + * + * @return void + */ + public function allow_cors() + { + header("Access-Control-Allow-Origin: *"); + } + + /** + * Define the routes of the application + * + * @return void + */ + public function add_default_routes() + { + add_action('rest_api_init', function() { + register_rest_route('api', '/login', array( + 'methods' => 'POST', + 'callback' => [$this, 'login_user']), + ); + register_rest_route('api', '/logoff', array( + 'methods' => 'POST', + 'callback' => [$this, 'logoff_user']), + ); + register_rest_route('api', '/favorite', array( + 'methods' => 'POST', + 'callback' => [$this, 'favorite_post']) + ); + }); + } + + /** + * Make WP login + * + * @return void process the login in Rest API + */ + public function login_user() + { + $get = file_get_contents('php://input'); + $g = json_decode($get, true); + + if(empty($g['user_login'])) { + return wp_send_json(array( + "title" => "Erro!", + "text" => "É necessário preencher o username" + ), 422); + } + + if(empty($g['user_password'])) { + return wp_send_json(array( + "title" => "Erro!", + "text" => "É necessário preencher a senha" + ), 422); + } + + $creds = array( + 'user_login' => sanitize_text_field($g['user_login']), + 'user_password' => sanitize_text_field($g['user_password']), + 'remember' => true + ); + + $user = wp_signon($creds, false); + + if ( is_wp_error( $user ) ) { + return wp_send_json(array( + 'logged' => false, + "title" => "Erro!", + "text" => $user->get_error_message() + ), 422); + } + + $token = wp_generate_password(32, false); + update_user_meta($user->ID, 'auth_token', $token); + + return wp_send_json(array( + 'logged' => true, + 'message' => 'Login executado com sucesso!', + 'token' => $token + ), 200); + } + + /** + * Get the Token + * + * @return array|string|null returns the user token or null + */ + public function get_the_token() + { + $headers = getallheaders(); + $token = isset($headers['Authorization']) ? str_replace('Bearer ', '', $headers['Authorization']) : null; + + return $token; + } + + /** + * Logoff the user + * + * @return string with the logoff information + */ + public function logoff_user() + { + $token = $this->get_the_token(); + + if ($token) { + $this->invalidate_token($token); + } + + wp_logout(); + return wp_send_json(array( + 'logged' => false, + 'message' => 'Logoff executado com sucesso!' + ), 200); + } + + /** + * Favorite/unfavorite a post + * + * @return string favorite/unfavorite the post + */ + public function favorite_post($request) + { + $token = $this->get_the_token(); + if (!$token) { + return wp_send_json(array( + "title" => "Erro!", + "text" => 'Token de autenticação não fornecido' + ), 401); + } + + $user = $this->get_user_by_token($token); + if (!$user) { + return wp_send_json(array( + "title" => "Erro!", + "text" => 'Token de autenticação inválido' + ), 401); + } + + $get = file_get_contents('php://input'); + $g = json_decode($get, true); + + if(empty($g['post_id']) || !(is_numeric($g['post_id']))) { + return wp_send_json(array( + 'success' => false, + "title" => "Erro!", + "text" => "É necessário enviar a ID do POST" + ), 422); + } + + $get_post = get_post($g['post_id']); + if (!$get_post) { + return wp_send_json(array( + 'success' => false, + "title" => "Erro!", + "text" => "Este post não existe na nossa plataforma" + ), 422); + } + + // verificar se existe o registro + global $wpdb; + $table = $wpdb->prefix."favorite"; + $user_id = (int) $user->ID; + $post_id = (int) $g['post_id']; + + // Sanitização adicional + $user_id = sanitize_key($user_id); + $post_id = sanitize_key($post_id); + + $results = $wpdb->get_results($wpdb->prepare("SELECT id FROM $table WHERE `post_id`=%d and `user_id`=%d", $post_id, $user_id)); + + if ($results) { + $wpdb->delete($table, array('post_id' => $post_id, 'user_id' => $user_id)); + return wp_send_json(array( + 'success' => true, + "title" => "Sucesso!", + "text" => "Você desfavoritou este post" + ), 200); + } + + $wpdb->insert($table, array('post_id' => $post_id, 'user_id' => $user_id, 'fav_date' => current_time('mysql')), array('%d', '%d', '%s')); + return wp_send_json(array( + 'success' => true, + "title" => "Sucesso!", + "text" => "Você favoritou este post" + ), 200); + } + + /** + * Invalidate the given token + * + * @param string $token The token to invalidate + * @return void + */ + private function invalidate_token($token) + { + global $wpdb; + $user_id = $wpdb->get_var($wpdb->prepare( + "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'auth_token' AND meta_value = %s", + $token + )); + + if ($user_id) { + delete_user_meta($user_id, 'auth_token'); + } + } + + /** + * Create a valid token + * + * @param string $token The token to validate + * @return void + */ + private function get_user_by_token($token) + { + global $wpdb; + $user_id = $wpdb->get_var($wpdb->prepare( + "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'auth_token' AND meta_value = %s", + $token + )); + + return $user_id ? get_user_by('id', $user_id) : null; + } +} + +$app = new RoutesWordpressPlugin(); \ No newline at end of file diff --git a/wp-content/plugins/mateus-avila-isidoro/classes/uninstall.php b/wp-content/plugins/mateus-avila-isidoro/classes/uninstall.php new file mode 100644 index 00000000..51a2f47f --- /dev/null +++ b/wp-content/plugins/mateus-avila-isidoro/classes/uninstall.php @@ -0,0 +1,26 @@ +prefix."favorite"; + $sql = "DROP TABLE IF EXISTS $table"; + $wpdb->query( $sql ); + } +} + +$app = new UninstallWordpressPlugin(); \ No newline at end of file diff --git a/wp-content/plugins/mateus-avila-isidoro/mateus-avila-isidoro.php b/wp-content/plugins/mateus-avila-isidoro/mateus-avila-isidoro.php new file mode 100644 index 00000000..70a6f4fc --- /dev/null +++ b/wp-content/plugins/mateus-avila-isidoro/mateus-avila-isidoro.php @@ -0,0 +1,18 @@ +