You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

309 lines
12 KiB

<?php
// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
//
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id:
//author : aris002@yahoo.co.uk
namespace TikiLib\Socnets\TikiHybrid;
require_once('lib/socnets/Util.php');
use TikiLib\Socnets\Util\Util;
require_once('lib/socnets/LLOG.php');
//use TikiLib\Socnets\LLOG\LLOG;
require_once('lib/socnets/PrefsGen.php');
use TikiLib\Socnets\PrefsGen\PrefsGen;
use Hybridauth\Logger\LoggerInterface;
use Hybridauth\Logger;
use Hybridauth\Exception\Exception;
use Hybridauth\Hybridauth;
use Hybridauth\HttpClient;
use TikiLib;
use Feedback;
use Tracker_Definition;
use Services_Tracker_Utilities;
use Tiki\Lib\Logs\LogsLib;
class TikiHybrid extends LogsLib
{
//TODO when for strings assign null or when ''? or don't need anything?
protected static string $socPreffix = 'socnets_';
protected string $namedpreffix = '';
protected string $providerName = '';
public $adapter = null;
public $logger = null;
public static string $logpath = '/var/log/httpd/errors/tikihybrid.log';
public function __construct($providerName)
{
try {
global $prefs;
$this -> providerName = $providerName;
self::$socPreffix = PrefsGen::getSocPreffix();
$this->namedprefix = self::$socPreffix . $providerName;
Util::log2('tikiHybrid constructor namedprefix:', $this -> namedprefix);
//we need to use Guzzle due to errors with curl!
$guzzle = new HttpClient\Guzzle(null, [
'verify' => false # Set to false to disable SSL certificate verification
]);
//maybe later for testing to separate logs for each provider?
//$this->logger = new Logger\Logger(true, self::$logpath);
//Feedback::warning(Util::getLogFile());
if (! $this->isRegistered()) {
Feedback::error(tr('TikiHybrid __construct: this site is not registered with ' . $this->$providerName));
// do we need to land on tiki-admin.php?
header('Location: tiki-index.php');
// header('Location: tiki-admin.php'); //?page=socialnetworks');
die();
}
$this -> config =
[
'callback' => PrefsGen::getPrefsSocLoginBaseUrl() . $providerName,
'enabled' => $prefs[$this->namedprefix . '_loginEnabled'],
'keys' => [
'id' => $prefs[$this->namedprefix . '_app_id'],
'secret' => $prefs[$this->namedprefix . '_app_secret'],
],
//'scope' => $value['scope'], //TODO TEST hybridauth reaction to : 'scope' => null or empty?
];
// LLOG('tikiHybrid constructor config:', $this -> config );
$adapterClass = '\\Hybridauth\\Provider\\' . $providerName;
$this -> adapter = new $adapterClass($this -> config, $guzzle);
//$this->hybridauth = new Hybridauth($confhybrid, $guzzle, null, $this->logger );
// LLOG('tikiHybrid constructed :)' );
} catch (Throwable $e) {
error_log($e->getMessage());
//echo TikiHybrid construct error:' . $e->getMessage();
Feedback::error('TikiHybrid construct error: ' . $e->getMessage());
}
}
// we might send just hybridauth adapter after testing
public function login()
{
global $prefs, $user;
$userlib = TikiLib::lib('user');
try {
$tokens = $this->adapter->getAccessToken();
$accessToken = $tokens['access_token'];
$userProfile = $this->adapter->getUserProfile();
$userId = $userProfile->identifier;
//email not needed here
//$email = $userProfile->email;
// LLOG('login email=', $email);
// LLOG('login tokens=', $tokens);
// LLOG('login accessToken=', $accessToken);
//TODO remove after tests!!!
//Feedback::note("socnet_id : " . $socnet_id);
//Feedback::note("namedprefix : " . $namedprefix);
if (! $user) {
//TODO do we need to test this here? Can someone suddenly dissable login even if
//we checked this at the begining?
if ($prefs[$this->namedprefix . '_loginEnabled'] != 'y') {
Feedback::error(tra('Login to this site using ' . $this->providerName . ' is disabled. Contact admin.'));
return false;
}
//this one is slow. It would be good to make it faster. Need to find out how.
//$local_user = $this->getOne("select `user` from `tiki_user_preferences` where `prefName` = ? and `value` = ?", [ 'facebook_id', $socnet_id]);
$local_user = $this -> getOne("select `user` from `tiki_user_preferences` where `prefName` = ? and `value` = ?", [$this->namedprefix . '_id', $userId]);
// Feedback::note('local_user: '. $local_user);
if ($local_user) {
$user = $local_user;
} elseif ($prefs[$this->namedprefix . '_autocreateuser'] === 'y') {
//Feedback::error( tra('Creating new users is disabled for ' . $providerName ));
$local_user = $this->createUser($userProfile);
}
if ($local_user) {
$user = $local_user;
} else {
Feedback::error(tra('You need to link your local account to ' . $this->providerName . ' before you can login using it'));
header('Location: tiki-index.php');
die;
}
global $user_cookie_site;
$_SESSION[$user_cookie_site] = $user;
$userlib->update_expired_groups();
$this->set_user_preference($user, $this->namedprefix . '_id', $userId);
$this->set_user_preference($user, $this->namedprefix . '_token', $accessToken);
$userlib->update_lastlogin($user);
//TODO photoURL works for facebook and google but need to test for other socnets
$photoURL = strtok($userProfile->photoURL, '?') . '?access_token=' . $accessToken;
// LLOG('login photoURL=' . $photoURL);
// LLOG('createUser start accesToken=' , $accessToken);
$avatarlib = TikiLib::lib('avatar');
$avatarlib->set_avatar_from_url($photoURL, $user);
Feedback::note('Welcome, ' . $userProfile->firstName . ' ' . $userProfile->lastName . '!');
//TODO save visitors page and to land there?
header('Location: tiki-index.php');
die;
} else { //relogin if logged in?
$this->set_user_preference($user, $this->namedprefix . '_id', $userId);
$this->set_user_preference($user, $this->namedprefix . '_token', $accessToken);
}
} catch (Throwable $e) {
Feedback::error('TikiHybrid login error: ' . $e->getMessage());
}
}
/**
* Checks if the site is registered with a social network like facebook etc. (application id , api key and secret are set)
*
* @return bool true, if this site is registered with a social network like facebook etc.
*/
private function isRegistered()
{
//if ($name === "" or not in the list?)
//TODO add "is enabled"? and maybe is there a better test?
global $prefs;
return ($prefs[$this -> namedprefix . '_app_id'] != '' && $prefs[$this -> namedprefix . '_app_secret'] != '');
}
/**
* Creates a new tiki user from a socnet user profile
*
* @returns $user it created
*/
//TODO save newly created users token!
private function createUser($userProfile)
{
global $prefs, $user;
$userlib = TikiLib::lib('user');
if ($prefs[$this->namedprefix . '_autocreateuser'] != 'y') {
Feedback::error(tr('TikiHybrid is not allowed to create a new user with your ' . $this->providerName . ' account. Please contact administrator.'));
return $user;
}
$userId = $userProfile->identifier;
$email = $userProfile->email;
// LLOG('createUser start email=', $email);
$firstName = $userProfile->firstName;
$lastName = $userProfile->lastName;
// $email = $prefs[$namedprefix . '_autocreate_userFromEmail'] == 'y' ? $userProfile->email : '';
// TODO we need change to _autocreate_userFromEmail for the sake of clarity?
$autoEmail = $prefs[$this->namedprefix . '_autocreate_email'] === 'y' ? $email : '';
// LLOG('createUser autoEmail=', $autoEmail);
// IMPORTANT TODO test user creation below line is true!
$autoUser = $prefs['login_is_email'] === 'y' ? $autoEmail : '';
$autoPrefixedId = $prefs[ $this->namedprefix . '_autocreate_prefix'] . $userId;
$randompass = $userlib->genPass();
// LLOG('createUser autoUser=', $autoUser);
if ($autoUser) {
$user = $userlib->add_user($autoUser, $randompass, $email);
} else {
$user = $userlib->add_user($autoPrefixedId, $randompass, $email);
}
// Feedback::error(tr('TikiHybrid is asked to link your account with: ' . $providerName . ' But it is not implemented yet in Tiki.'));
if (! $user) {
$err_msg = tr('TikiHybrid unable to create a new user:' . $user . ' with your ' . $this->providerName . ' account. You might already have an account and need to link. But it is not implemented yet.');
//error_log($err_msg);
Feedback::error($err_msg);
} else {
Feedback::note('TikiHybrid from ' . $this->providerName . ' has created a new user: ' . $user);
}
//TODO check if user trackers work correctly
$ret = $userlib->get_usertrackerid("Registered");
$userTracker = $ret['usersTrackerId'];
$userField = $ret['usersFieldId'];
$isAutoNames = $prefs[$this->namedprefix . '_autocreate_names'];
if ($prefs[$this->namedprefix . '_autocreate_user_trackeritem'] === 'y' && $userTracker && $userField) {
$definition = Tracker_Definition::get($userTracker);
$utilities = new Services_Tracker_Utilities();
$fields = ['ins_' . $userField => $user];
//TODO check this! it was ! empty($autoNames)
//tracker items
$autoNames = ''; //[2,3]; //??
if ($isAutoNames === 'y') {
$names = array_map('trim', explode(',', $autoNames));
$fields['ins_' . $names[0]] = $firstName;
$fields['ins_' . $names[1]] = $lastName;
}
$utilities->insertItem(
$definition,
[
'status' => '',
'fields' => $fields,
'validate' => false,
]
);
}
$this->set_user_preference($user, 'realName', $firstName . ' ' . $lastName);
// if ($prefs['socialnetworks_facebook_firstloginpopup'] == 'y') {
// $this->set_user_preference($user, 'socialnetworks_user_firstlogin', 'y');
// }
// if ($prefs['feature_userPreferences'] == 'y') {
// $fb_avatar = json_decode($this->facebookGraph('', 'me/picture', ['type' => 'square', 'width' => '480', 'redirect' => '0','access_token' => $access_token], false, 'GET'));
// }
return $user;
}
//this when Hybridauth class is used.
public function checkConnectedAdapters()
{
$adapters = $this->hybridauth->getConnectedAdapters();
if ($adapters) {
Feedback::warning('TikiHybrid has connected adapters: ' . count($adapters));
} else {
Feedback::warning('TikiHybrid has NO connected adapters.');
}
}
}