Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 6849 | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |

<?php
/**
 * 
 * Este controllador agrupa las funciones de Callback para todas las operaciones de OAUTH
 */
namespace LeadersLinked\Controller;


use Laminas\Db\Adapter\AdapterInterface;

use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\Log\LoggerInterface;
use Laminas\View\Model\JsonModel;
use GeoIp2\Database\Reader As GeoIp2Reader;
use LeadersLinked\Model\UserProvider;
use LeadersLinked\Mapper\UserMapper;
use LeadersLinked\Mapper\UserProviderMapper;
use LeadersLinked\Model\User;
use LeadersLinked\Model\UserType;
use LeadersLinked\Authentication\AuthSocialAdapter;
use LeadersLinked\Library\Functions;
use LeadersLinked\Library\Image;
use LeadersLinked\Library\Facebook;
use LeadersLinked\Model\Provider;
use LeadersLinked\Mapper\UserBrowserMapper;
use LeadersLinked\Model\UserBrowser;
use LeadersLinked\Mapper\UserIpMapper;
use LeadersLinked\Model\UserIp;

class OauthController extends AbstractActionController
{
    /**
     *
     * @var \Laminas\Db\Adapter\AdapterInterface
     */
    private $adapter;
    
    /**
     *
     * @var \LeadersLinked\Cache\CacheInterface
     */
    private $cache;
    
    
    /**
     *
     * @var \Laminas\Log\LoggerInterface
     */
    private $logger;
    
    /**
     *
     * @var array
     */
    private $config;
    
    
    /**
     *
     * @var \Laminas\Mvc\I18n\Translator
     */
    private $translator;
    
    
    /**
     *
     * @param \Laminas\Db\Adapter\AdapterInterface $adapter
     * @param \LeadersLinked\Cache\CacheInterface $cache
     * @param \Laminas\Log\LoggerInterface LoggerInterface $logger
     * @param array $config
     * @param \Laminas\Mvc\I18n\Translator $translator
     */
    public function __construct($adapter, $cache, $logger, $config, $translator)
    {
        $this->adapter      = $adapter;
        $this->cache        = $cache;
        $this->logger       = $logger;
        $this->config       = $config;
        $this->translator   = $translator;
    }
    
    public function indexAction()
    {
        return new JsonModel(['success' => false, 'error' => 'Missing authentication']);
    }
    
    /**
     * 
     * @param string $id
     * @param string $name
     * @param string $email
     * @param string $picture
     * @param string $provider
     */
    private function process($id , $name, $email, $picture, $provider)
    {
        $flashMessenger = $this->plugin('FlashMessenger');
        if(empty($id) || empty($name) || empty($email)) 
        {
            if($provider == UserProvider::PROVIDER_FACEBOOK) {
                $flashMessenger->addErrorMessage('ERROR_FACEBOOK_AUTH');
            }
            if($provider == UserProvider::PROVIDER_TWITTER) {
                $flashMessenger->addErrorMessage('ERROR_TWITTER_AUTH');
            }
            if($provider == UserProvider::PROVIDER_GOOGLE) {
                $flashMessenger->addErrorMessage('ERROR_GOOGLE_AUTH');
            }

            $this->logger->err('Parámetro(s) inválido(s) [id = ' . $id . ' email = ' . $email .' name = ' . $name . ' picture = ' . $picture, ['ip' => Functions::getUserIP()]);

            return  $this->redirect()->toRoute('home');
        }

        
        $userMapper = UserMapper::getInstance($this->adapter);
        $userProviderMapper = UserProviderMapper::getInstance($this->adapter);
        $userProvider = $userProviderMapper->fetchOneByIdAndProdiver($id, $provider);
        
        //El usuario tiene una sesión activa
        $currentUserPlugin = $this->plugin('currentUserPlugin');
        $currentUser = $currentUserPlugin->getUser();
        if($currentUser) {
            
            if(!$currentUser->image) {
                $this->downloadImage($picture, $currentUser, $userMapper);
            }
            
            if(!$userProvider) {
                
                $userProvider = new UserProvider();
                $userProvider->user_id = $currentUser->id;
                $userProvider->id = $id;
                $userProvider->name = $name;
                $userProvider->email = $email;
                $userProvider->image = $picture;
                $userProvider->provider = $provider;
                
                if($userProviderMapper->insert($userProvider)) {
                    
                    if($provider == UserProvider::PROVIDER_FACEBOOK) {
                        $this->logger->info('Registro del token de Facebook', ['user_id' => $currentUser->id, 'ip' => Functions::getUserIP()]);
                    }
                    if($provider == UserProvider::PROVIDER_TWITTER) {
                        $this->logger->info('Registro del token de Twitter', ['user_id' => $currentUser->id, 'ip' => Functions::getUserIP()]);
                    }
                    if($provider == UserProvider::PROVIDER_GOOGLE) {
                        $this->logger->info('Registro del token de  Google', ['user_id' => $currentUser->id, 'ip' => Functions::getUserIP()]);
                    }
                
                
                } else {
                    $flashMessenger->addErrorMessage('ERROR_FACEBOOK_AUTH');
                }
            }
            
            $this->registerBroserAndIp($currentUser);
            
            return $this->redirect()->toRoute('account-settings', [], ['query'=>['tab'=>'nav-social-networks']]);
            
        } else {
            //El usuario no tiene sesión activa
        
            //Si existe la cuenta del provider en el sistema recuperamos el usuario
            if($userProvider) {
                $user = $userMapper->fetchOne($userProvider->user_id);
            } else {
                //Buscamos si esta registrado el usuario por email   
                $user = $userMapper->fetchOneByEmail($email);
                
                //Creamos un usuario
                if(empty($user))
                {
                   
                    
                    
                    $names = explode(' ', $name);
                    $user = new User();
                    $user->email                = $email;
                    $user->first_name           = $names[0];
                    $user->last_name            = count($names) > 1 ?  implode(' ', array_slice($names, 1)) : '';
                    $user->usertype_id          = UserType::USER;
                    $user->password             = '';
                    $user->activation_key       = '';
                    $user->status               = User::STATUS_ACTIVE;
                    $user->blocked              = User::BLOCKED_NO;
                    $user->email_verified       = User::EMAIL_VERIFIED_YES;
                    $user->login_attempt        = 0;
                    $user->balance              = 0;
                    
        
                    if($userMapper->insert($user)) {
                        $this->logger->info('Creamos el usuario usando los datos del provider', ['user_id' => $user->id, 'ip' => Functions::getUserIP()]);
                   
                    } else {
                        $flashMessenger->addErrorMessage($userMapper->getError());
                        return  $this->redirect()->toRoute('home');
                    }
                    $user = $userMapper->fetchOne($user->id);
                }
                if($user) {
                    if(!$user->image) {
                        $this->downloadImage($picture, $user, $userMapper);
                    }
                    $userProvider = new UserProvider();
                    $userProvider->user_id = $user->id;
                    $userProvider->id = $id;
                    $userProvider->name = $name; 
                    $userProvider->email = $email;
                    $userProvider->image = $picture;
                    $userProvider->provider = $provider;
                        
                    if($userProviderMapper->insert($userProvider)) {
                        if($provider == UserProvider::PROVIDER_FACEBOOK) {
                            $this->logger->info('Registro del token de Facebook', ['user_id' => $user->id, 'ip' => Functions::getUserIP()]);
                        }
                        if($provider == UserProvider::PROVIDER_TWITTER) {
                            $this->logger->info('Registro del token de Twitter', ['user_id' => $user->id, 'ip' => Functions::getUserIP()]);
                        }
                        if($provider == UserProvider::PROVIDER_GOOGLE) {
                            $this->logger->info('Registro del token de  Google', ['user_id' => $user->id, 'ip' => Functions::getUserIP()]);
                        }
                    }
                }
            }
    
    
            
            $authSocialAdapter = new AuthSocialAdapter($this->adapter, $this->logger);
            $authSocialAdapter->setData($id, $provider);
            
            $authService = new \Laminas\Authentication\AuthenticationService();
            $authService->setAdapter($authSocialAdapter);
            
            
            $result = $authService->authenticate();
            if($result->getCode() == \Laminas\Authentication\Result::SUCCESS) 
            {
                if($provider == UserProvider::PROVIDER_FACEBOOK) {
                    $this->logger->info('Acceso Facebook', ['user_id' => $user->id, 'ip' => Functions::getUserIP()]);
                }
                if($provider == UserProvider::PROVIDER_TWITTER) {
                    $this->logger->info('Acceso Twitter', ['user_id' => $user->id, 'ip' => Functions::getUserIP()]);
                }
                if($provider == UserProvider::PROVIDER_GOOGLE) {
                    $this->logger->info('Acceso Google', ['user_id' => $user->id, 'ip' => Functions::getUserIP()]);
                }
                
                $this->registerBroserAndIp($user);
                
                
                return $this->redirect()->toRoute('dashboard');
            } 
            else 
            {
                $message = $result->getMessages()[0];
                $flashMessenger->addErrorMessage($message);
                
                return  $this->redirect()->toRoute('home');
            }
        }
    }
    
    /**
     * 
     * @param string $picture
     * @param User $user
     * @param UserMapper $userMapper
     */
    private function downloadImage($picture, $user, $userMapper)
    {
        $target_path = $this->config['leaderslinked.fullpath.user'] . $user->uuid;
        
        $picture_content = file_get_contents($picture);
        if($picture_content) {
            $temp_file = tempnam(sys_get_temp_dir(), 'Tux');
            file_put_contents($temp_file, $picture_content);
            
            $target_filename    = 'user-' . uniqid() . '.png';
            list( $target_width, $target_height ) = explode('x', $this->config['leaderslinked.image_sizes.user_size']);
            $source             = $temp_file;
            $crop_to_dimensions = true;
            if(Image::uploadImage($source, $target_path, $target_filename, $target_width, $target_height, $crop_to_dimensions)) {
                $user->image = $target_filename;
                $userMapper->updateImage($user);
            } 
        }
    }
    
    public function facebookAction() 
    {
        $flashMessenger = $this->plugin('FlashMessenger');
        
        $app_id = $this->config['leaderslinked.facebook.app_id'];
        $app_password = $this->config['leaderslinked.facebook.app_password'];
        $app_graph_version = $this->config['leaderslinked.facebook.app_graph_version'];
        
        
        
        if(!isset($_GET['code']) && !isset($_GET['state']))
        {
            $flashMessenger->addErrorMessage('Facebook code or state not available');
            return $this->redirect()->toRoute('home');
        }
        //$code   = Functions::sanitizeFilterString($_GET['code']);
        $state  = Functions::sanitizeFilterString($_GET['state']);
            
        $fb = new \Facebook\Facebook([
            'app_id' => $app_id,
            'app_secret' => $app_password,
            'default_graph_version' => $app_graph_version
        ]);
            
        $helper = $fb->getRedirectLoginHelper();
        $helper->getPersistentDataHandler()->set('state', $state);
 
        $accessToken = null;
        try {
            $accessToken = $helper->getAccessToken();
        } 
        catch(\Facebook\Exceptions\FacebookResponseException $e) 
        {
            $this->logger->err('Facebook Graph: ' . $e->getMessage(), ['ip' => Functions::getUserIP()]);
            $flashMessenger->addErrorMessage('ERROR_FACEBOOK_AUTH');

            return $this->redirect()->toRoute('home');
        } 
        catch(\Facebook\Exceptions\FacebookSDKException $e) 
        {
            $this->logger->err('Facebook SDK: ' . $e->getMessage(), ['ip' => Functions::getUserIP()]);
            $flashMessenger->addErrorMessage('ERROR_FACEBOOK_AUTH');
            
            return $this->redirect()->toRoute('home');
        }
        

        
        if (!$accessToken) {
            if ($helper->getError()) {
                $flashMessenger->addErrorMessage('ERROR_FACEBOOK_AUTH');
                $this->logger->err($helper->getErrorDescription(), ['ip' => Functions::getUserIP()]);

                return $this->redirect()->toRoute('home');
            } else {
                $flashMessenger->addErrorMessage('ERROR_FACEBOOK_AUTH');
                $this->logger->err('Facebook Bad request', ['ip' => Functions::getUserIP()]);
                
               
                return $this->redirect()->toRoute('home');
            }
        }
            
        try {
            $response = $fb->get('/me?fields=id,name,email,picture',  $accessToken->getValue());
        } catch(\Facebook\Exceptions\FacebookResponseException $e) {
            $this->logger->err('Facebook Graph: ' . $e->getMessage(), ['ip' => Functions::getUserIP()]);
            $flashMessenger->addErrorMessage('ERROR_FACEBOOK_AUTH');
            
        } catch(\Facebook\Exceptions\FacebookSDKException $e) {
            $this->logger->err('Facebook SDK: ' . $e->getMessage(), ['ip' => Functions::getUserIP()]);
            $flashMessenger->addErrorMessage('ERROR_FACEBOOK_AUTH');
            
            return $this->redirect()->toRoute('home');
        }
 
        $fb_user = $response->getGraphUser();
        if(is_object($fb_user)) {
            $id      = Functions::sanitizeFilterString($fb_user->getId());
            $name    = Functions::sanitizeFilterString($fb_user->getName());
            $email   = filter_var($fb_user->getEmail(), FILTER_SANITIZE_EMAIL);
            $picture = $fb_user->getPicture();
            if(is_array($picture)) {
                $picture = filter_var($picture['url'], FILTER_SANITIZE_URL);
            } else if(is_object($picture)) {
                $picture = filter_var($picture->getUrl(), FILTER_SANITIZE_URL);
            } else {
                $picture = filter_var($picture, FILTER_SANITIZE_URL);
            }
        }
            
        return $this->process($id, $name, $email, $picture, UserProvider::PROVIDER_FACEBOOK);

    }
    
    public function facebookDeleteAction()
    {
        error_log('---START FACEBOOK DELETE---');
        error_log('GET');
        error_log(print_r($_GET, true));
        error_log('POST');
        error_log(print_r($_POST, true));
        error_log('---END FACEBOOK DELETE---');

        
        return new JsonModel([
            'success' => true,
        ]);
        
    }
    
    public function facebookCancelAction() 
    {
        $signed_request = $_POST['signed_request'] ? Functions::sanitizeFilterString($_POST['signed_request']) : '';
        if($signed_request) {
            $facebook = new \LeadersLinked\Library\Facebook($this->config);
            $data = $facebook->parse_signed_request($signed_request);
            if($data && $data['user_id']) {
                $userProviderMapper = UserProviderMapper::getInstance($this->adapter);
                $userProvider = $userProviderMapper->fetchOneByIdAndProdiver($data['user_id'], Provider::FACEBOOK);
                if($userProvider) {
                    if($userProviderMapper->deleteByIdAndProvider($userProvider->id, $userProvider->provider)) {
                        $this->logger->info('Se borro la cuenta de Facebook');
                        return new JsonModel([
                            'success' => true,
                        ]);
                    } 
                }
            }
        }
        
        return new JsonModel([
            'success' => false,
        ]);
    }

    public function googleAction() 
    {
        $currentUserPlugin = $this->plugin('currentUserPlugin');
        $currentUser = $currentUserPlugin->getUser();
        
        $google = new \Google_Client();
        $google->setAuthConfig('data/google/auth-leaderslinked/apps.google.com_secreto_cliente.json');
        $google->setAccessType("offline");        // offline access
        $google->setIncludeGrantedScopes(true);   // incremental auth
        
        $google->addScope('profile');
        $google->addScope('email');
        
        
        if (! isset($_GET['code'])) {
            $auth_url = $google->createAuthUrl();
            return $this->redirect()->toUrl(filter_var($auth_url, FILTER_SANITIZE_URL));
        } 

        $google->authenticate(Functions::sanitizeFilterString($_GET['code']));
        $accessToken = $google->getAccessToken();
        
        if(empty($accessToken)) {
            $flashMessenger = $this->plugin('FlashMessenger');
            $flashMessenger->addErrorMessage('Google access token is wrong');
            
            
            
            
            return $this->redirect()->toRoute('home');
        }
            
        $userInfo   = $google->verifyIdToken();
        if(!is_array($userInfo) || empty($userInfo['sub']) || empty($userInfo['name']) || empty($userInfo['email']) || empty($userInfo['picture'])) {
            $flashMessenger = $this->plugin('FlashMessenger');
            $flashMessenger->addErrorMessage('Google verify token is wrong');
            return $this->redirect()->toRoute('home');
        }
        
        $id         = Functions::sanitizeFilterString($userInfo['sub']);
        $name       =Functions::sanitizeFilterString($userInfo['name']);
        $email      = filter_var($userInfo['email'], FILTER_SANITIZE_EMAIL);
        $picture    = filter_var($userInfo['picture'], FILTER_SANITIZE_URL);
        
        return $this->process($id, $name, $email, $picture, UserProvider::PROVIDER_GOOGLE);
    }
    
    public function twitterAction()
    {
        if($this->config['leaderslinked.runmode.sandbox']) {
            
            $twitter_api_key = $this->config['leaderslinked.twitter.sandbox_api_key'];
            $twitter_api_secret = $this->config['leaderslinked.twitter.sandbox_api_secret'];
            
        } else {
            $twitter_api_key = $this->config['leaderslinked.twitter.production_api_key'];
            $twitter_api_secret = $this->config['leaderslinked.twitter.production_api_secret'];
        }
        
        $twitterSession = new \Laminas\Session\Container('twitter');
        
        $request_token = [];
        $request_token['oauth_token']           = $twitterSession->oauth_token;
        $request_token['oauth_token_secret']    = $twitterSession->oauth_token_secret;
        
        if (isset($_GET['oauth_token']) && $request_token['oauth_token'] !== $_GET['oauth_token']) {
            // Abort! Something is wrong.
            
            
            $flashMessenger = $this->plugin('FlashMessenger');
            $flashMessenger->addErrorMessage('Twitter Oauth token is wrong');
            return $this->redirect()->toRoute('home');
        }
        
        $twitter = new  \Abraham\TwitterOAuth\TwitterOAuth($twitter_api_key, $twitter_api_secret, $request_token['oauth_token'], $request_token['oauth_token_secret']);
        $access_token = $twitter->oauth('oauth/access_token', ['oauth_verifier' => $_GET['oauth_verifier']]);
        
        $oauth_token        = $access_token['oauth_token'];
        $oauth_token_secret = $access_token['oauth_token_secret'];
        
        /*
         stdClass Object ( [id] => 144499524 [id_str] => 144499524 [name] => Efrain Yanez R [screen_name] => eyanezve [location] => [description] => [url] => [entities] => stdClass Object ( [description] => stdClass Object ( [urls] => Array ( ) ) ) [protected] => 1 [followers_count] => 30 [friends_count] => 44 [listed_count] => 0 [created_at] => Sun May 16 13:36:21 +0000 2010 [favourites_count] => 5 [utc_offset] => [time_zone] => [geo_enabled] => [verified] => [statuses_count] => 0 [lang] => [contributors_enabled] => [is_translator] => [is_translation_enabled] => [profile_background_color] => C0DEED [profile_background_image_url] => http://abs.twimg.com/images/themes/theme1/bg.png [profile_background_image_url_https] => https://abs.twimg.com/images/themes/theme1/bg.png [profile_background_tile] => [profile_image_url] => http://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png [profile_image_url_https] => https://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png [profile_link_color] => 1DA1F2 [profile_sidebar_border_color] => C0DEED [profile_sidebar_fill_color] => DDEEF6 [profile_text_color] => 333333 [profile_use_background_image] => 1 [has_extended_profile] => 1 [default_profile] => 1 [default_profile_image] => 1 [following] => [follow_request_sent] => [notifications] => [translator_type] => none [suspended] => [needs_phone_verification] => [email] => eyanezve@gmail.com )
         */


        $twitter = new  \Abraham\TwitterOAuth\TwitterOAuth($twitter_api_key, $twitter_api_secret, $oauth_token, $oauth_token_secret);
        $response =  $twitter->get('account/verify_credentials', ['include_entities' => true, 'skip_status' => true, 'include_email' => true]);
        
        $id         = $response->id ? Functions::sanitizeFilterString($response->id) : '';
        $name       = $response->name ? Functions::sanitizeFilterString($response->name) : '';
        $email      = isset($response->email) ? filter_var($response->email, FILTER_SANITIZE_EMAIL) : '';
        $picture    = isset($response->profile_image_url_https) ? filter_var($response->profile_image_url_https, FILTER_SANITIZE_URL) : '';
               
        return $this->process($id, $name, $email, $picture, UserProvider::PROVIDER_TWITTER);
    }
    
    private function registerBroserAndIp($user)
    {
        $navigator = get_browser(null, true);
        $device_type    =  $navigator['device_type'];
        $platform       =  $navigator['platform'];
        $browser        =  $navigator['browser'];
        
        $userBrowserMapper = UserBrowserMapper::getInstance($this->adapter);
        $userBrowser = $userBrowserMapper->fetch($user->id, $device_type, $platform, $browser);
        if($userBrowser) {
            $userBrowserMapper->update($userBrowser);
        } else {
            $userBrowser = new UserBrowser();
            $userBrowser->user_id           = $user->id;
            $userBrowser->browser           = $browser;
            $userBrowser->platform          = $platform;
            $userBrowser->device_type       = $device_type;
            $userBrowser->is_tablet         = intval( $navigator['istablet']);
            $userBrowser->is_mobile_device  = intval( $navigator['ismobiledevice']);
            $userBrowser->version           = $navigator['version'];
            
            $userBrowserMapper->insert($userBrowser);
        }
        //
        
        $ip = Functions::getUserIP();
        $ip = $ip == '127.0.0.1' ? '148.240.211.148' : $ip;
        
        $userIpMapper = UserIpMapper::getInstance($this->adapter);
        $userIp = $userIpMapper->fetch($user->id, $ip);
        if(empty($userIp)) {
            
            if($this->config['leaderslinked.runmode.sandbox']) {
                $filename = $this->config['leaderslinked.geoip2.production_database'];
            } else {
                $filename = $this->config['leaderslinked.geoip2.sandbox_database'];
            }
            
            $reader = new GeoIp2Reader($filename); //GeoIP2-City.mmdb');
            $record = $reader->city($ip);
            if($record) {
                $userIp = new UserIp();
                $userIp->user_id = $user->id;
                $userIp->city = Functions::utf8_decode($record->city->name);
                $userIp->state_code = Functions::utf8_decode($record->mostSpecificSubdivision->isoCode);
                $userIp->state_name = Functions::utf8_decode($record->mostSpecificSubdivision->name);
                $userIp->country_code = Functions::utf8_decode($record->country->isoCode);
                $userIp->country_name = Functions::utf8_decode($record->country->name);
                $userIp->ip = $ip;
                $userIp->latitude = $record->location->latitude;
                $userIp->longitude = $record->location->longitude;
                $userIp->postal_code =  $record->postal->code;
                
                $userIpMapper->insert($userIp);
            }
            
            
        } else {
            $userIpMapper->update($userIp);
        }
    }
}