53 lines
1.6 KiB
PHP
53 lines
1.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Auth;
|
|
|
|
use App\Models\Auth\DingTalkIdentity;
|
|
use App\Models\Auth\DingTalkOAuthState;
|
|
use App\Models\Auth\User;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class DingTalkIdentityBinder
|
|
{
|
|
public function bindFromToken(?string $token, User $user): bool
|
|
{
|
|
if (! is_string($token) || trim($token) === '') {
|
|
return false;
|
|
}
|
|
|
|
return DB::transaction(function () use ($token, $user): bool {
|
|
$state = DingTalkOAuthState::query()
|
|
->where('binding_token_hash', hash('sha256', $token))
|
|
->lockForUpdate()
|
|
->first();
|
|
|
|
if (! $state || $state->expires_at->isPast() || ! $state->union_id) {
|
|
return false;
|
|
}
|
|
|
|
$unionOwner = DingTalkIdentity::query()->where('union_id', $state->union_id)->first();
|
|
if ($unionOwner && (int) $unionOwner->user_id !== (int) $user->id) {
|
|
return false;
|
|
}
|
|
|
|
$userIdentity = DingTalkIdentity::query()->where('user_id', $user->id)->first();
|
|
if ($userIdentity && $userIdentity->union_id !== $state->union_id) {
|
|
return false;
|
|
}
|
|
|
|
DingTalkIdentity::query()->updateOrCreate(
|
|
['user_id' => $user->id],
|
|
[
|
|
'union_id' => $state->union_id,
|
|
'open_id' => $state->open_id,
|
|
'nickname' => $state->nickname,
|
|
]
|
|
);
|
|
|
|
$state->forceFill(['binding_token_hash' => null])->save();
|
|
|
|
return true;
|
|
});
|
|
}
|
|
}
|