Files
IPB/system/Login/Vkontakte.php
T
2025-12-19 05:38:56 -08:00

253 lines
8.2 KiB
PHP

<?php
namespace IPS\Login;
class _Vkontakte extends LoginAbstract
{
/**
* @brief Icon
*/
public static $icon = 'vk';
/**
* Get Form
*
* @param \IPS\Http\Url $url The URL for the login page
* @return string
*/
public function loginForm( $url, $ucp=FALSE )
{
$url = \IPS\Http\Url::internal( 'applications/core/interface/vkontakte/auth.php', 'none' );
if ( $ucp )
{
$state = "ucp-" . \IPS\Session::i()->csrfKey;
}
else
{
$state = \IPS\Dispatcher::i()->controllerLocation . "-" . \IPS\Session::i()->csrfKey;
}
return \IPS\Theme::i()->getTemplate( 'login', 'core', 'global' )->vkontakte( "https://oauth.vk.com/authorize?client_id={$this->settings['app_id']}&amp;scope=email&amp;redirect_uri=".urlencode( $url ) . "&amp;state={$state}&amp;response_type=code" );
}
/**
* Authenticate
*
* @param string $url The URL for the login page
* @param \IPS\Member $member If we want to integrate this login method with an existing member, provide the member object
* @return \IPS\Member
* @throws \IPS\Login\Exception
*/
public function authenticate( $url, $member=NULL )
{
$url = $url->setQueryString( 'loginProcess', 'vkontakte' );
try
{
/* Get a token */
try
{
$response = \IPS\Http\Url::external( "https://oauth.vk.com/access_token?client_id={$this->settings['app_id']}&redirect_uri=".(string) \IPS\Http\Url::internal( 'applications/core/interface/vkontakte/auth.php', 'none' )."&client_secret={$this->settings['app_secret']}&code=".\IPS\Request::i()->code
)->request()->get()->decodeJson();
}
catch( \RuntimeException $e )
{
throw new \IPS\Login\Exception( 'generic_error', \IPS\Login\Exception::INTERNAL_ERROR );
}
/* Get the user data */
$userData = $response;
if(!isset($userData['email'])) throw new \IPS\Login\Exception( 'В вашем аккаунте ВК отсутствует email, укажите его!', \IPS\Login\Exception::INTERNAL_ERROR );
/* Find or create member */
$newMember = FALSE;
if ( $member === NULL )
{
$member = \IPS\Member::load( $userData['email'], 'email' );
if ( !$member->member_id )
{
$member = new \IPS\Member;
if ( \IPS\Settings::i()->reg_auth_type == 'admin' or \IPS\Settings::i()->reg_auth_type == 'admin_user' )
{
$member->members_bitoptions['validating'] = TRUE;
}
$member->member_group_id = \IPS\Settings::i()->member_group;
$member->email = $userData['email'];
$member->profilesync = json_encode( array( 'vkontakte' => array( 'photo' => TRUE, 'cover' => FALSE, 'status' => TRUE ) ) );
$newMember = TRUE;
$name1 = \IPS\Http\Url::external( "https://api.vk.com/method/users.get?user_id={$userData['user_id']}&v=5.29&access_token={$response['access_token']}&fields=first_name,last_name,screen_name,bdate,nickname" )->request()->get()->decodeJson();
$member->name = $name1['response'][0]['nickname'];
if ( empty($member->name) AND $this->settings['real_name'] )
{
$name = $name1['response'][0]['first_name'].' '.$name1['response'][0]['last_name'];
$existingUsername = \IPS\Member::load( $name, 'name' );
if ( !$existingUsername->member_id )
{
$member->name = $name;
}
}
}
}
$member->vk_uid = $userData['user_id'];
$member->vk_token = $response['access_token'];
$member->save();
/* Sync */
if ( $newMember )
{
if ( \IPS\Settings::i()->reg_auth_type == 'admin_user' )
{
\IPS\Db::i()->update( 'core_validating', array( 'user_verified' => 1 ), array( 'member_id=?', $member->member_id ) );
}
$sync = new \IPS\core\ProfileSync\VK( $member );
$sync->sync();
}
/* Return */
return $member;
}
catch ( \IPS\Http\Request\Exception $e )
{
throw new \IPS\Login\Exception( 'generic_error', \IPS\Login\Exception::INTERNAL_ERROR );
}
}
public static function link( \IPS\Member $member, $details )
{
try {
$userData = \IPS\Http\Url::external( "https://api.vk.com/method/users.get?uid={$details[1]}&access_token={$details[0]}&fields=first_name,last_name,screen_name,bdate,nickname" )->request()->get()->decodeJson();
$userData = $userData['response'][0];
$member->vk_id = $details[1];
$member->vk_token = $details[0];
$member->save();
}catch(\Exception $e) {}
}
/**
* ACP Settings Form
*
* @param string $url URL to redirect user to after successful submission
* @return array List of settings to save - settings will be stored to core_login_handlers.login_settings DB field
* @code
return array( 'savekey' => new \IPS\Helpers\Form\[Type]( ... ), ... );
* @endcode
*/
public function acpForm()
{
$where = array( array( 'template_group=?', 'login' ) );
$where[] = array( 'template_app=?', 'core' );
$where[] = array( 'template_location=?', 'global' );
$results = array();
$selects = \IPS\Db::i()->select( 'template_name', 'core_theme_templates', $where );
$selects->rewind();
while($selects->valid())
{
$results[ $selects->current() ] = $selects->current();
$selects->next();
}
$results = array_unique( $results );
//if(\IPS\IN_DEV) {
if(!in_array('vkontakte',$results)) {
ob_start();?>
<ips:template parameters="$url" />
<a href='{$url}' class='ipsButton ipsButton_verySmall ipsButton_fullWidth ipsSocial ipsSocial_vk' style="background-color:#56789C;">
<span class='ipsSocial_icon'><i class='fa fa-vk'></i></span>
<span class='ipsSocial_text'>{lang="login_vkontakte"}</span>
</a>
<?
$html = ob_get_contents();
ob_end_clean();
$params = array();
/* Parse the header tag */
preg_match( '/^<ips:template parameters="(.+?)?" \/>\n/', $html, $params );
/* Strip it */
$html = ( isset($params[0]) ) ? str_replace( $params[0], '', $html ) : $html;
$id=0;
\IPS\Db::i()->insert( 'core_theme_templates', array( 'template_set_id' => $id,
'template_app' => 'core',
'template_added_to' => $id,
'template_location' => 'global',
'template_group' => 'login',
'template_name' => 'vkontakte',
'template_data' => ( isset( $params[1] ) ) ? $params[1] : '',
'template_content' => $html,
'template_updated' => time(),
'template_unique_key' => md5( $id . ';' . 'core' . ';' . 'global' . ';' . 'login' . ';' . ( 'vkontakte' ) ),
'template_removable' => $id ) );
\IPS\Theme::load( \IPS\Theme::i()->defaultTheme() )->compileTemplates( 'core' );
}
/*}elseif(!in_array('vkontakte',$results)) {
\IPS\Output::i()->sidebar['actions'] = array(
'help' => array(
'link' => \IPS\Http\Url::internal( '&app=core&module=settings&controller=login&do=form&id=vkontakte' ),
'title' => 'Шаблоны не синхронизированы. Включите DEV-режим и перезагрузите страницу!',
),
);
}*/
return array(
'app_id' => new \IPS\Helpers\Form\Text( 'login_vkontakte_app', ( isset( $this->settings['app_id'] ) ) ? $this->settings['app_id'] : '', TRUE ),
'app_secret' => new \IPS\Helpers\Form\Text( 'login_vkontakte_secret', ( isset( $this->settings['app_secret'] ) ) ? $this->settings['app_secret'] : '', TRUE ),
'real_name' => new \IPS\Helpers\Form\YesNo( 'login_real_name', ( isset( $this->settings['real_name'] ) ) ? $this->settings['real_name'] : FALSE, TRUE )
);
}
/**
* Test Settings
*
* @return bool
* @throws \InvalidArgumentException
*/
public function testSettings()
{
return TRUE;
}
/**
* Can a member sign in with this login handler?
* Used to ensure when a user disassociates a social login that they have some other way of logging in
*
* @param \IPS\Member $member The member
* @return bool
*/
public function canProcess( \IPS\Member $member )
{
return ( $member->vk_id and $member->vk_token );
}
/**
* Can a member change their email/password with this login handler?
*
* @param string $type 'email' or 'password'
* @param \IPS\Member $member The member
* @return bool
*/
public function canChange( $type, \IPS\Member $member )
{
return FALSE;
}
}