OAuth (part 5 draft)

This commit is contained in:
Visman 2023-05-10 21:21:33 +07:00
parent 76350bc12e
commit 9107637d4e
6 changed files with 149 additions and 12 deletions

View file

@ -13,6 +13,7 @@ namespace ForkBB\Models\Pages;
use ForkBB\Core\Validator;
use ForkBB\Core\Exceptions\MailException;
use ForkBB\Models\Page;
use ForkBB\Models\Provider\Driver;
use ForkBB\Models\User\User;
use function \ForkBB\__;
@ -84,19 +85,60 @@ class RegLog extends Page
if ($this->user->isGuest) {
$uid = $this->c->providerUser->findUser($provider);
// логин
if ($uid > 0) {
$args = [
'user' => $this->c->users->load($uid),
];
return $this->c->Auth->login($args, 'POST');
// регистрация
} else {
if (empty($uid)) {
// на форуме есть пользователь с таким email
if ($this->c->providerUser->findEmail($provider) > 0) {
$auth = $this->c->Auth;
$auth->fIswev = ['i', ['Email message', __($provider->name)]];
return $auth->forget([], 'GET', $provider->userEmail);
}
if (1 !== $this->c->config->b_regs_allow) {
return $this->c->Message->message('No new regs');
}
$user = $this->c->users->create();
$user->username = $this->nameGenerator($provider);
$user->password = \password_hash($this->c->Secury->randomPass(72), \PASSWORD_DEFAULT);
$user->group_id = $this->c->config->i_default_user_group;
$user->email = $provider->userEmail;
$user->email_confirmed = $provider->userEmailVerifed ? 1 : 0;
$user->activate_string = '';
$user->u_mark_all_read = \time();
$user->email_setting = $this->c->config->i_default_email_setting;
$user->timezone = $this->c->config->o_default_timezone;
$user->language = $this->user->language;
$user->style = $this->user->style;
$user->registered = \time();
$user->registration_ip = $this->user->ip;
$user->ip_check_type = 0;
$user->signature = '';
$user->location = $provider->userLocation;
$user->url = $provider->userURL;
$newUserId = $this->c->users->insert($user);
if (true !== $this->c->providerUser->registration($user, $provider)) {
throw new RuntimeException('Failed to insert data'); // ??????????????????????????????????????????
}
$this->c->Log->info('OAuth Reg: ok', [
'user' => $user->fLog(),
'provider' => $provider->name,
'userInfo' => $provider->userInfo,
'headers' => true,
]);
} else {
$user = $this->c->users->load($uid);
}
// вход
return $this->c->Auth->login(['user' => $user], 'POST');
// пользователь
} else {
@ -104,4 +146,42 @@ class RegLog extends Page
exit(var_dump($provider->userId, $provider->userName, $provider->userEmail, $this->c->NormEmail->normalize($provider->userEmail)));
}
/**
* Подбирает уникальное имя для регистрации пользователя
*/
protected function nameGenerator(Driver $provider): string
{
$names = [];
if ('' != $provider->userName) {
$names[] = $provider->userName;
}
if ('' != $provider->userLogin) {
$names[] = $provider->userLogin;
}
if ('' != ($tmp = (string) \strstr($provider->userEmail, '@', true))) {
$names[] = $tmp;
}
$names[] = 'user' . \time();
$v = $this->c->Validator->reset()->addRules(['name' => 'required|string:trim|username|noURL:1']);
$end = '';
$i = 0;
while ($i < 100) {
foreach ($names as $name) {
if ($v->validation(['name' => $name . $end])) {
return $v->name;
}
}
$end = '_' . $this->c->Secury->randomHash(4);
++$i;
}
throw new RuntimeException('Failed to generate unique username');
}
}

View file

@ -210,6 +210,11 @@ abstract class Driver extends Model
*/
abstract protected function getuserId(): string;
/**
* Возвращает логин пользователя (от провайдера)
*/
abstract protected function getuserLogin(): string;
/**
* Возвращает имя пользователя (от провайдера)
*/

View file

@ -71,7 +71,7 @@ class GitHub extends Driver
return false;
}
$this->userInfo = $userInfo;
$this->userInfo = $this->c->Secury->replInvalidChars($userInfo);
return true;
}
@ -84,12 +84,20 @@ class GitHub extends Driver
return (string) ($this->userInfo['id'] ?? '');
}
/**
* Возвращает логин пользователя (от провайдера)
*/
protected function getuserLogin(): string
{
return (string) ($this->userInfo['login'] ?? '');
}
/**
* Возвращает имя пользователя (от провайдера)
*/
protected function getuserName(): string
{
return (string) ($this->userInfo['name'] ?? ($this->userInfo['login'] ?? ''));
return (string) ($this->userInfo['name'] ?? '');
}
/**
@ -129,7 +137,7 @@ class GitHub extends Driver
*/
protected function getuserLocation(): string
{
return (string) ($this->userInfo['location'] ?? '');
return \mb_substr((string) ($this->userInfo['location'] ?? ''), 0, 30, 'UTF-8');
}
/**

View file

@ -13,6 +13,7 @@ namespace ForkBB\Models\ProviderUser;
use ForkBB\Core\Container;
use ForkBB\Models\Model;
use ForkBB\Models\Provider\Driver;
use ForkBB\Models\User\User;
use PDO;
use RuntimeException;
@ -78,4 +79,35 @@ class ProviderUser extends Model
return $count ? \array_pop($result) : 0;
}
/**
* Создает новую связь между пользователем и провайдером
*/
public function registration(User $user, Driver $provider): bool
{
if ($user->isGuest) {
throw new RuntimeException('User expected, not guest');
}
if ('' == $provider->userId) {
throw new RuntimeException('The user ID is empty');
}
if ('' == $provider->userEmail) {
throw new RuntimeException('The user email is empty');
}
$vars = [
':uid' => $user->id,
':name' => $provider->name,
':userid' => $provider->userId,
':email' => $provider->userEmail,
':normal' => $this->c->NormEmail->normalize($provider->userEmail),
':verif' => $provider->userEmailVerifed ? 1 : 0,
];
$query = 'INSERT INTO ::providers_users (uid, pr_name, pu_uid, pu_email, pu_email_normal, pu_email_verified)
VALUES (?i:uid, ?s:name, ?s:userid, ?s:email, ?s:normal, ?i:verif)';
return false !== $this->c->DB->exec($query, $vars);
}
}

View file

@ -77,3 +77,9 @@ msgstr "cURL error."
msgid "User error"
msgstr "User data request failed."
msgid "No new regs"
msgstr "This board is not accepting new registrations."
msgid "Email message"
msgstr "This email received from %s belongs to a registered user.<br>Perhaps you used another provider to sign in or username + passphrase?"

View file

@ -77,3 +77,9 @@ msgstr "Ошибка cURL."
msgid "User error"
msgstr "Ошибка запроса данных пользователя."
msgid "No new regs"
msgstr "Форум закрыт для новых регистраций."
msgid "Email message"
msgstr "Данный электронный адрес, полученный от %s, принадлежит зарегистрированному пользователю.<br>Возможно, вы использовали другого провайдера для входа или имя + кодовую фразу?"