Re: [Tiki-devel] Social Libs and logins revamp

Jonny Bradley via TikiWiki-devel <[email protected]>
Newsgroups gmane.comp.cms.tiki.devel
Message-ID <[email protected]>
Hi Aris

Nice too see you around again!

Will re-reply once i've had a chance to absorb this properly, looks promising.

Meanwhile, we've (finally) moved to git so you could do a WIP MR (work in progress merge request) here https://gitlab.com/tikiwiki/tiki/ and i'll try and have a play with it... at least we can see it in colour! :)

jonny




> On 27 Feb 2021, at 14:21, Arijus Bernotas via TikiWiki-devel <[email protected]> wrote:
> 
> Hi all fantastic people,
> 
> After some struggle with hybridauth (to make it work with tiki  - practically I had to fork it) I switched to phpleague and made it work easily. But the current tiki code structure for social logins forces to create different files in the root of tiki for each social network which can grow to hundreds or thousands. e.g tiki-socialnetworks-facebook.php etc.
> 
> So,
> 
> Q1: First of all, do we need  all kind SocialLib extends LogsLibs?
> 
> Q2: Or is better class TikiFacebook extends TikiSocial or it would be even possible to have one TikiSocial class and construct an instance by sending config params accordingly to each socnetwork?
> 
> Q3: Is it better to create a separate folder/s for socnetworks and/or their logins? If yes , then where?
> 
> Please have in mind that I have strong C++ paradigms in mind... :)
> 
> P.S. I hope to have working public demo very soon again because my eu domain after brexit stopped working...
> 
> Aris
> 
> Below is the code which I hope still works with phpleague and my forked hybridauth (some commented parts)  (needs changed parts )
> 
> <?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: tikifacebooklib.php 2019-12-08 aris002
> 
> // this script may only be included - so its better to die if called directly.
> if (strpos($_SERVER['SCRIPT_NAME'], basename(__FILE__)) !== false) {
>     header('location: index.php');
>     exit;
> }
> $logslib = TikiLib::lib('logs');
> 
> //Feedback::warning(tr('start tikifacebooklib'));
> 
> 
> /**
>  * This class serves facebook login into tiki functions
>  * Is it better to name it TikiFacebookLib or just TikiFacebook?
>  * @author aris002 and others. Please add yourself if you see your code...
>  */
> class TikiFacebookLib extends LogsLib
> {
>     private $graphVersion = 'v3.2'; //we can set it in preferences as well?
>     private    $config3;   //ending with "3" to remind us that the structures come from the third party. In this case - thephpleague.
>     private $provider3;
>     private $profile3;
>     private $access_token;
> 
>     public function __construct()
>     {
>         global $prefs;
> 
> 
>         if (! $this->isFacebookRegistered()) {
>             Feedback::error(tr('this site is not registered with Facebook!'));
>             // do we need to land on tiki-admin.php?
>             header('Location: tiki-index.php');
>             die();
>         }
> 
>         $this->config3 = [
>             'clientId'          => $prefs['socialnetworks_facebook_application_id'],
>             'clientSecret'      => $prefs['socialnetworks_facebook_application_secr'],
>             'redirectUri'       => $this->getURL(),
>             'graphApiVersion'   => $this->graphVersion,
>         ];
> 
>         $this->provider3 = new \League\OAuth2\Client\Provider\Facebook($this->config3);
> 
>     }
> 
> 
> 
>     /**
>      * retrieves the URL for the current page
>      *
>      * @return string    URL for the current page
>      */
>     function getURL()
>     {
>         $url = 'http';
>         $port = '';
>         if (! empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
>             $url .= 's';
>             if ($_SERVER['SERVER_PORT'] != 443 and strpos($_SERVER['HTTP_HOST'], ':') == 0) {
>                 $port = ':' . $_SERVER['SERVER_PORT'];
>             }
>         } else {
>             if ($_SERVER['SERVER_PORT'] != 80 and strpos($_SERVER['HTTP_HOST'], ':') == 0) {
>                 $port = ':' . $_SERVER['SERVER_PORT'];
>             }
>         }
>         $url .= '://' . $_SERVER['HTTP_HOST'] . $port . $_SERVER['REQUEST_URI'];
> //        Feedback::warning('inside tikifacebooklib getURL()=' . $url);
> 
>         return $url;
>     }
> 
> 
> 
>     /**
>      * Checks if the site is registered with facebook (application id , api key and secret are set)
>      *
>      * @return bool    true, if this site is registered with facebook as an application
>      */
>     function isFacebookRegistered()
>     {
>         global $prefs;
>         return ($prefs['socialnetworks_facebook_application_id'] != '' and $prefs['socialnetworks_facebook_application_secr'] != '');
>     }
> 
> 
> 
>     /**
>      * Partial login into tiki - tries to connect with facebook and to retrieve user's facebook profile
>      *
>      * @return bool    true, if login with facebook and user profile is ok
>      */
>     function loginPre()
>     {
>         global $prefs, $user;
> 
>         try {
>             $this->getAccessToken();
>             $fb_profile = $this->provider3->getResourceOwner($this->access_token);
>         }
>         catch (\Exception $e) {
>             Feedback::error(tr('Oops! We ran into an unknown issue: '.$e->getMessage() ));
>         }
> 
> 
>             if ( is_object($fb_profile) && ! empty( $fb_profile->getId() ) )
>             {
>                 $this->loginMain($access_token, $fb_profile);
>             }
> //            elseif (is_object($fb_profile) && is_object($fb_profile->error))  //do we need more precise errors?
> //            {
> //                Feedback::error($fb_profile->error->type . ': ' . $fb_profile->error->message);
> //                return false;
> //            }
>             else
>             {
>                 Feedback::error(tr('Oops! Facebook profile information has not been retrieved!'));
>                 return false;
>             }
> 
> 
>         return true;
>     }
> 
> 
> 
>     /**
>      * @return Facebook    access token, if all is ok
>      */
>     function getAccessToken()
>     {
>             $this->access_token = $this->provider3->getAccessToken('authorization_code', [ 'code' => $_GET['code']    ] );
>             return $this->access_token;
>     }
> 
> 
> 
>     /**
>     * This is where a real login with access_token and facebook profile fb_profile into your tiki happens
>     * @return bool true, if all is ok
>     */
>     function loginMain($access_token, $fb_profile)
>     {
>         global $prefs, $user;
> 
>         $userlib = TikiLib::lib('user');
> //        $fid = $fb_profile->id;
>         $fb_id = $fb_profile->getId();
> //        Feedback::warning("fid" . ': ' . $fb_id);
> 
>         if (! $user) {
>             if ($prefs['socialnetworks_facebook_login'] != 'y') {
>                 return false;
>             }
> 
> //            $local_user = $this->getOne("select `user` from `tiki_user_preferences` where `prefName` = 'facebook_id' and `value` = ?", [$fb_profile->id]);
>             $local_user = $this->getOne("select `user` from `tiki_user_preferences` where `prefName` = 'facebook_id' and `value` = ?", [$fb_id]);
> //            Feedback::warning("local_user" . ': ' . $local_user);
> 
> 
>             if ($local_user) {
>                 $user = $local_user;
>             } elseif ($prefs['socialnetworks_facebook_autocreateuser'] == 'y') {
>                 $local_user = $this->createUser($access_token, $fb_profile);
>             }
> 
>             if ($local_user) {
>                 $user = $local_user;
>             } else {
>                 $smarty = TikiLib::lib('smarty');
>                 $smarty->assign('errortype', 'login');
>                 $smarty->assign('msg', tra('You need to link your local account to Facebook before you can login using it'));
>                 $smarty->display('error.tpl');
>                 die;
>             }
> 
>             global $user_cookie_site;
>             $_SESSION[$user_cookie_site] = $user;
>             $userlib->update_expired_groups();
>             $this->set_user_preference($user, 'facebook_id', $fb_id);
>             $this->set_user_preference($user, 'facebook_token', $access_token);
>             $userlib->update_lastlogin($user);
>             header('Location: tiki-index.php');
>             die;
>         } else { //relogin if logged in?
>             $this->set_user_preference($user, 'facebook_id', $fb_id);
>             $this->set_user_preference($user, 'facebook_token', $access_token);
>         }
>         return true;    //do we need this?
>     }
> 
> 
> 
>     /**
>      * if this site is registered with facebook, it redirects to facebook to ask for a request token
>      *
>      */
>     function requestAuthorization()
>     {
>         global $prefs;
>         $scopes = [];
> //        if ($prefs['socialnetworks_facebook_publish_stream'] == 'y') {
> //        $scopes[] = 'publish_actions';
> //        }
>         if ($prefs['socialnetworks_facebook_manage_events'] == 'y') {
>             $scopes[] = 'create_event';
>             $scopes[] = 'rsvp_event';
>         }
>         if ($prefs['socialnetworks_facebook_sms'] == 'y') {
>             $scopes[] = 'sms';
>         }
>         if ($prefs['socialnetworks_facebook_manage_pages'] == 'y') {
>             $scopes[] = 'manage_pages';
>         }
>         if ($prefs['socialnetworks_facebook_email'] === 'y') {
>             $scopes[] = 'email';
>         }
>         $scope = implode(',', $scopes);
>         $url = $this->getURL();
>         if (strpos($url, '?') != 0) {
>             $url = preg_replace('/\?.*/', '', $url);
>         }
>         $url = urlencode($url . '?request_facebook');
>         $url = 'https://www.facebook.com/' . $this->graphVersion . '/dialog/oauth?client_id='
>             . $prefs['socialnetworks_facebook_application_id'] . '&scope=' . $scope . '&redirect_uri=' . $url;
> 
>     //    Feedback::warning(tr('inside tikifacebooklib requestAuthorization'));
>         header("Location: $url");
>         die();
>     }
> 
>     /**
>      * Creates a new tiki user from a facebook profile
>      *
>      * @returns $user it created
>      */
>     function createUser($access_token, $fb_profile)
>     {
>         global $prefs, $user;
>         $userlib = TikiLib::lib('user');
> 
>         $randompass = $userlib->genPass();
>         $email = $prefs['socialnetworks_facebook_email'] === 'y' ? $fb_profile->email : '';
>         if ($prefs['login_is_email'] == 'y' && $email) {
>             $user = $email;
>         } elseif ($prefs['login_autogenerate'] == 'y') {
>             $user = '';
>         } else {
>             $user = 'fb_' . $fb_profile->id;
>         }
>         $user = $userlib->add_user($user, $randompass, $email);
> 
>         if (! $user) {
>             $smarty = TikiLib::lib('smarty');
>             $smarty->assign('errortype', 'login');
>             $smarty->assign('msg', tra('We were unable to create a new user with your Facebook account. Please contact the administrator.'));
>             $smarty->display('error.tpl');
>             die;
>         }
> 
>         $ret = $userlib->get_usertrackerid("Registered");
>         $userTracker = $ret['usersTrackerId'];
>         $userField = $ret['usersFieldId'];
>         if ($prefs['socialnetworks_facebook_create_user_trackeritem'] == 'y' && $userTracker && $userField) {
>             $definition = Tracker_Definition::get($userTracker);
>             $utilities = new Services_Tracker_Utilities();
>             $fields = ['ins_' . $userField => $user];
>             if (! empty($prefs['socialnetworks_facebook_names'])) {
>                 $names = array_map('trim', explode(',', $prefs['socialnetworks_facebook_names']));
>                 $fields['ins_' . $names[0]] = $fb_profile->first_name;
>                 $fields['ins_' . $names[1]] = $fb_profile->last_name;
>             }
>             $utilities->insertItem(
>                 $definition,
>                 [
>                     'status' => '',
>                     'fields' => $fields,
>                     'validate' => false,
>                 ]
>             );
>         }
> 
>         $this->set_user_preference($user, 'realName', $fb_profile->name);
>         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'));
>             $avatarlib = TikiLib::lib('avatar');
> $avatarlib->set_avatar_from_url($fb_avatar->data->url, $user);
>         }
> 
>         return $user;
>     }
> 
>     /**
>      * Do we still need this?
>      * Talking to Facebook via the graph api at "https://graph.facebook.com/" using fsockopen
>      *
>      * @param    string $user     userId of the user to send the request for
>      * @param    string $action   directory/file part of the graph api URL
>      * @param    array  $params   parameters for the api call, each entry is one element submitted in the request
>      * @param    bool   $addtoken should the access token be added to the parameters if the calling function did not pass this parameter
>      *
>      * @param string    $method
>      *
>      * @return    string                body of the response page (json encoded object)
>      * @throws Exception
>      */
>     function facebookGraph($user, $action, $params, $addtoken = true, $method = 'POST')
>     {
>         if (! $this->facebookRegistered()) {
>             $this->add_log('facebookGraph', 'application not set up');
>             return false;
>         }
>         if ($addtoken) {
>             $token = $this->get_user_preference($user, 'facebook_token', '');
>             if ($token == '') {
>                 $this->add_log('facebookGraph', 'user not registered with facebook');
>                 return false;
>             }
> 
>             if (! isset($params['access_token'])) {
>                 $params['access_token'] = $token;
>             }
>         }
> 
>         // set up http client to make request
>         $url = 'https://graph.facebook.com/' . $this->graphVersion . '/' . $action;
>         if (! empty($params) && is_array($params) && $method === 'GET') {
>             // set url this way instead of using setUri and setParameterGet to avoid failure in some environments
>             $url .= '?' . urldecode(http_build_query($params, '', '&'));
>         }
>         $client = TikiLib::lib('tiki')->get_http_client($url);
>         $client->setMethod($method);
>         if (! empty($params) && is_array($params) && $method === 'POST') {
>             $client->setParameterPost($params);
>         }
>         // make request
>         $response = $client->send();
>         return $response->getBody();
>     }
> 
>     /**
>      *
>      * publish a message (status or link with more options) on facebook
>      *
>      * @param string    $user        userId of the user to send for
>      * @param string    $message    message/main text to send
>      * @param string    $url        optional URL to pass along
>      * @param string    $text        optional text to show for the URL
>      * @param string    $caption    optional caption of the message accompanying the url
>      * @param string    $privacy    currently unused as I did not find the docu on how to use the privacy settings
>      *
>      * @return    string|bool            false on error, object Id of the message on success
>      */
>     function facebookWallPublish($user, $message, $url = '', $text = '', $caption = '', $privacy = '')
>     {
>         $params = [];
>         if ($url != '') {
>             $params['link'] = $url;
>             if ($text != '') {
>                 $params['name'] = $text;
>             }
>             if ($caption != '') {
>                 $params['caption'] = $caption;
>             }
>             $params['description'] = $message;
>         } else {
>             $params['message'] = substr($message, 0, 400);
>         }
>         $ret = $this->facebookGraph($user, 'me/feed/', $params);
>         $result = json_decode($ret);
>         if (isset($result->id)) {
>             return $result->id;
>         } else {
>             return false;
>         }
>     }
> 
>     /**
>      * like an object on facebook
>      *
>      * @param string    $user        userId of the user to send for
>      * @param string    $facebookId    id of the object to like
>      *
>      * @return    string|bool            false on error, object Id of the message on success
>      */
>     function facebookLike($user, $id)
>     {
>         $params = [];
>         $ret = $this->facebookGraph($user, "$id/likes/", $params);
>         return json_decode($ret);
>     }
> 
> 
> 
>     /**
>      * TODO Use something from phpLeague or remove?
>      */
>     function getFacebookUserProfile($access_token)
>     {
>         global $prefs;
> 
>         $fields = ['id', 'name', 'first_name', 'last_name'];
> 
>         if ($prefs['socialnetworks_facebook_email'] == 'y') {
>             $fields[] = 'email';
>         }
> 
>         $resp = $this->facebookGraph('', 'me', ['fields' => implode(',', $fields),'access_token' => $access_token], false, 'GET');
>         $fb_profile = json_decode($resp);
> 
>         return $fb_profile;
>     }
> 
> }
> 
> global $tikifacebooklib;
> 
> $tikifacebooklib = new TikiFacebookLib();
> 
> 
> 
> _______________________________________________
> TikiWiki-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/tikiwiki-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.