OAuth (part 5 draft)
This commit is contained in:
parent
76350bc12e
commit
9107637d4e
6 changed files with 149 additions and 12 deletions
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -210,6 +210,11 @@ abstract class Driver extends Model
|
|||
*/
|
||||
abstract protected function getuserId(): string;
|
||||
|
||||
/**
|
||||
* Возвращает логин пользователя (от провайдера)
|
||||
*/
|
||||
abstract protected function getuserLogin(): string;
|
||||
|
||||
/**
|
||||
* Возвращает имя пользователя (от провайдера)
|
||||
*/
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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?"
|
||||
|
|
|
@ -77,3 +77,9 @@ msgstr "Ошибка cURL."
|
|||
|
||||
msgid "User error"
|
||||
msgstr "Ошибка запроса данных пользователя."
|
||||
|
||||
msgid "No new regs"
|
||||
msgstr "Форум закрыт для новых регистраций."
|
||||
|
||||
msgid "Email message"
|
||||
msgstr "Данный электронный адрес, полученный от %s, принадлежит зарегистрированному пользователю.<br>Возможно, вы использовали другого провайдера для входа или имя + кодовую фразу?"
|
||||
|
|
Loading…
Add table
Reference in a new issue