CaiWuXiTong/app/Services/Auth/DingTalkIdentityBinder.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;
});
}
}