File: /home/reachcon/www/wp-content/themes/reach-connects/api.php
<?php
// Add ACF Fields to rest API
function my_rest_prepare_post($data, $post, $request) {
$_data = $data->data;
$fields = get_field_objects($post->ID);
if(is_array($fields) && count($fields)>0){
foreach ($fields as $key=>$value){
if($value['type']=='oembed'){
$video_url = get_field('video_url', $post->ID, FALSE);
$video_thumb_url = get_video_thumbnail_uri($video_url);
$_data[$key.'_thumbnail'] = $video_thumb_url;
$code = get_field($key, $post->ID);
$_data[$key] = str_replace(array('%', '"'), array('%p', '%q'), $code);
}else{
$_data[$key] = get_field($key, $post->ID);
}
}
}
// Add Featured Image
if( has_post_thumbnail() ){
$_data['featured_image'] = array(
'full'=>get_the_post_thumbnail_url($post->ID,'full'),
'thumb'=>get_the_post_thumbnail_url($post->ID,'Thumbnail')
);
}else{
$_data['featured_image'] = array(
'full'=>'https://www.pocketrestaurantconsultant.com/wp-content/uploads/default-article.png',
'thumb'=>'https://www.pocketrestaurantconsultant.com/wp-content/uploads/default-article-150x150.png',
);
}
$data->data = $_data;
return $data;
}
add_filter("rest_prepare_post", 'my_rest_prepare_post', 10, 3);
add_filter("rest_prepare_videos", 'my_rest_prepare_post', 10, 3);
add_filter("rest_prepare_recipes", 'my_rest_prepare_post', 10, 3);
// API Check Password
function rest_api_login($data){
if( !empty($data['user']) && !empty($data['pass']) ){
$user = $data['user'];
$pass = base64_decode($data['pass']);
$user = wp_authenticate( $user, $pass );
if(isset($user->ID)){
$args = array(
'id' => $user->ID,
'user' => $user->user_login,
'email' => $user->user_email,
'display' => $user->display_name,
);
$token = rest_api_token_create($args);
if($token){
$articles = wp_count_posts();
$articles = (isset($articles->publish)) ? $articles->publish : '0';
$videos = wp_count_posts('videos');
$videos = (isset($videos->publish)) ? $videos->publish : '0';
$recipes = wp_count_posts('recipes');
$recipes = (isset($recipes->publish)) ? $recipes->publish : '0';
$documents = wp_count_posts('documents');
$documents = (isset($documents->publish)) ? $documents->publish : '0';
$result = array(
'token' => $token,
'result' => 1,
'articles' => $articles,
'videos' => $videos,
'recipes' => $recipes,
'documents' => $documents
);
}else{ $result = array('result'=>4); }
}else{
////////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO
// check for brute force attacks
// $result = array('result'=>10);
$result = array('result'=>2); // invalid username or password
}
}else{ $result = array('result'=>3); }
return $result;
}
function rest_api_register($data){
if( !empty($data['user']) && !empty($data['pass']) ){
$user = $data['user'];
$email = $data['email'];
$fname = $data['fname'];
$lname = $data['lname'];
$pass = base64_decode($data['pass']);
$user_id = username_exists( $user );
if(!$user_id){ // Check if username is used
if( email_exists($email) == false ){ // check if email is used
$user_id = wp_create_user( $user, $pass, $email );
if( is_wp_error( $user_id ) ){
$result = array('result'=>2);
}else{
// Success!
$user_update = wp_update_user(
array(
'ID' => $user_id,
'first_name' => $fname,
'last_name' => $lname,
'show_admin_bar_front' => 'false', // This is used on the website end
)
);
if( is_wp_error( $user_update ) ){
wp_delete_user( $user_id );
$result = array('result'=>2);
}else{
$result = array('result'=>1); // Success
}
}
}else{ $result = array('result'=>4); }
}else{ $result = array('result'=>3); }
}else{ $result = array('result'=>2); }
return $result;
}
function rest_api_email($data){
if($data['email']!=''){
if( email_exists($data['email']) == false ){ return array('result'=>1); }
else{ return array('result'=>0); }
}else{ return array('result'=>0); }
}
function rest_api_username($data){
if($data['user']!=''){
$user_id = username_exists( $data['user'] );
if( is_wp_error( $user_id ) ){ return array('result'=>0); }
else{
if($user_id){ return array('user'=>$user_id,'result'=>0); }
else{ return array('user'=>$user_id,'result'=>1); }
}
}else{ return array('result'=>0); }
}
function rest_api_verify($data){
if(!isset($data['token'])){ $result = array('result'=>2); }
else{
$token = rest_api_token_read($data['token']);
if($token){
$user = get_user_by( 'id', $token->id);
if(isset($user->ID)){
if( $token->user != $user->user_login || $token->email != $user->user_email || $token->display != $user->display_name ){ $result = array('result'=>3);}
else{
$articles = wp_count_posts();
$articles = (isset($articles->publish)) ? $articles->publish : '0';
$videos = wp_count_posts('videos');
$videos = (isset($videos->publish)) ? $videos->publish : '0';
$recipes = wp_count_posts('recipes');
$recipes = (isset($recipes->publish)) ? $recipes->publish : '0';
$documents = wp_count_posts('documents');
$documents = (isset($documents->publish)) ? $documents->publish : '0';
$result = array(
'result' => 1,
'articles' => $articles,
'videos' => $videos,
'recipes' => $recipes,
'documents' => $documents
);
}
}else{ $result = array('result'=>2); }
}else{$result = array('result'=>2);}
}
return $result;
}
add_action( 'rest_api_init', function () {
//register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array( 'methods' => 'GET', 'callback' => 'my_awesome_func' ) );
// Check username and password and return token
register_rest_route( 'omada/v2', '/token/', array( 'methods' => 'POST', 'callback' => 'rest_api_login' ) );
// Check username and password and return token
register_rest_route( 'omada/v2', '/register/', array( 'methods' => 'POST', 'callback' => 'rest_api_register' ) );
// Get User Data on login if token is correct
register_rest_route( 'omada/v2', '/verify/', array( 'methods' => 'POST', 'callback' => 'rest_api_verify' ) );
// Check if email address is exists
register_rest_route( 'omada/v2', '/email/', array( 'methods' => 'POST', 'callback' => 'rest_api_email' ) );
// Check if username exists
register_rest_route( 'omada/v2', '/username/', array( 'methods' => 'POST', 'callback' => 'rest_api_username' ) );
// change email / pass
});
// Check against brute force attacks
function checkbrute($user_id) {
// Get timestamp of current time
$now = time();
// All login attempts are counted from the past 2 hours.
$attempts = $now - (5 * 60); //$now - (2 * 60 * 60);
// Collect Attempts
$bind=array(":attempts"=>$attempts,':id'=>$user_id);
$select = "user_id=:id AND time>:attempts LIMIT 20";
$results = $this->db->select("login_attempts", $select, $bind);
return count($results);
}
/**
* JSON Web Token implementation, based on this spec:
* http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06
* PHP version 5
* @category Authentication
* @package Authentication_JWT
* @author Neuman Vong <neuman@twilio.com>
* @author Anant Narayanan <anant@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
* @link https://github.com/firebase/php-jwt
*/
class JWT{
/**
* Decodes a JWT string into a PHP object.
* @param string $jwt The JWT
* @param string|null $key The secret key
* @param bool $verify Don't skip verification process
* @return object The JWT's payload as a PHP object
* @throws UnexpectedValueException Provided JWT was invalid
* @throws DomainException Algorithm was not provided
* @uses jsonDecode
* @uses urlsafeB64Decode
*/
public static function decode($jwt, $key = null, $verify = true){
$tks = explode('.', $jwt);
if (count($tks) != 3){ throw new UnexpectedValueException('Wrong number of segments'); }
list($headb64, $bodyb64, $cryptob64) = $tks;
if (null === ($header = JWT::jsonDecode(JWT::urlsafeB64Decode($headb64)))) {
throw new UnexpectedValueException('Invalid segment encoding');
}
if (null === $payload = JWT::jsonDecode(JWT::urlsafeB64Decode($bodyb64))) {
throw new UnexpectedValueException('Invalid segment encoding');
}
$sig = JWT::urlsafeB64Decode($cryptob64);
if ($verify){
if(empty($header->alg)){ throw new DomainException('Empty algorithm'); }
if ($sig != JWT::sign("$headb64.$bodyb64", $key, $header->alg)) {
throw new UnexpectedValueException('Signature verification failed');
}
}
return $payload;
}
/**
* Converts and signs a PHP object or array into a JWT string.
* @param object|array $payload PHP object or array
* @param string $key The secret key
* @param string $algo The signing algorithm. Supported
* algorithms are 'HS256', 'HS384' and 'HS512'
* @return string A signed JWT
* @uses jsonEncode
* @uses urlsafeB64Encode
*/
public static function encode($payload, $key, $algo = 'HS256'){
$header = array('typ' => 'JWT', 'alg' => $algo);
$segments = array();
$segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($header));
$segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($payload));
$signing_input = implode('.', $segments);
$signature = JWT::sign($signing_input, $key, $algo);
$segments[] = JWT::urlsafeB64Encode($signature);
return implode('.', $segments);
}
/**
* Sign a string with a given key and algorithm.
* @param string $msg The message to sign
* @param string $key The secret key
* @param string $method The signing algorithm. Supported
* algorithms are 'HS256', 'HS384' and 'HS512'
* @return string An encrypted message
* @throws DomainException Unsupported algorithm was specified
*/
public static function sign($msg, $key, $method = 'HS256'){
$methods = array( 'HS256' => 'sha256', 'HS384' => 'sha384', 'HS512' => 'sha512' );
if (empty($methods[$method])){ throw new DomainException('Algorithm not supported'); }
return hash_hmac($methods[$method], $msg, $key, true);
}
/**
* Decode a JSON string into a PHP object.
* @param string $input JSON string
* @return object Object representation of JSON string
* @throws DomainException Provided string was invalid JSON
*/
public static function jsonDecode($input){
$obj = json_decode($input);
if (function_exists('json_last_error') && $errno = json_last_error()) { JWT::_handleJsonError($errno); }
else if ($obj === null && $input !== 'null'){ throw new DomainException('Null result with non-null input'); }
return $obj;
}
/**
* Encode a PHP object into a JSON string.
* @param object|array $input A PHP object or array
* @return string JSON representation of the PHP object or array
* @throws DomainException Provided object could not be encoded to valid JSON
*/
public static function jsonEncode($input){
$json = json_encode($input);
if (function_exists('json_last_error') && $errno = json_last_error()) { JWT::_handleJsonError($errno); }
else if ($json === 'null' && $input !== null) { throw new DomainException('Null result with non-null input'); }
return $json;
}
/**
* Decode a string with URL-safe Base64.
* @param string $input A Base64 encoded string
* @return string A decoded string
*/
public static function urlsafeB64Decode($input){
$remainder = strlen($input) % 4;
if ($remainder){ $padlen = 4 - $remainder; $input .= str_repeat('=', $padlen); }
return base64_decode(strtr($input, '-_', '+/'));
}
/**
* Encode a string with URL-safe Base64.
* @param string $input The string you want encoded
* @return string The base64 encode of what you passed in
*/
public static function urlsafeB64Encode($input){ return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); }
/**
* Helper method to create a JSON error.
* @param int $errno An error number from json_last_error()
* @return void
*/
private static function _handleJsonError($errno){
$messages = array(
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON'
);
throw new DomainException( isset($messages[$errno]) ? $messages[$errno] : 'Unknown JSON error: ' . $errno );
}
}
// Create Token
function rest_api_token_create($arr){
try{ return JWT::encode($arr, NONCE_SALT); }catch(Exception $e){ return false; }
}
// Read JWT and return payload
function rest_api_token_read($token){
try{
$token = JWT::decode($token, NONCE_SALT);
if(!empty($token)){ return $token; }
return false;
}catch(Exception $e){
return false;
}
}