151 lines
6.2 KiB
PHP
151 lines
6.2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\SystemSettings;
|
|
|
|
use App\Models\Auth\DingTalkAuthAudit;
|
|
use App\Models\Auth\DingTalkBindingRequest;
|
|
use App\Models\Auth\DingTalkIdentity;
|
|
use App\Models\Auth\User;
|
|
use App\Services\Auth\DingTalkClosedAccess;
|
|
use App\Utilities\SystemAccess;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Routing\Controller;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class DingTalkBindings extends Controller
|
|
{
|
|
public function __construct()
|
|
{
|
|
$this->middleware(function ($request, $next) {
|
|
abort_unless(SystemAccess::canOpenSettings(), 403);
|
|
|
|
return $next($request);
|
|
});
|
|
}
|
|
|
|
public function index()
|
|
{
|
|
$eligibleUsers = $this->eligibleUsers()->with('roles')->orderBy('name')->get();
|
|
$eligibleUserIds = $eligibleUsers->pluck('id');
|
|
$bindingRequests = DingTalkBindingRequest::query()->with(['matchedUser', 'reviewer']);
|
|
$identities = DingTalkIdentity::query()->with('user');
|
|
$audits = DingTalkAuthAudit::query()->with(['user', 'actor']);
|
|
if (! SystemAccess::isSuperAdmin()) {
|
|
$bindingRequests->whereIn('matched_user_id', $eligibleUserIds);
|
|
$identities->whereIn('user_id', $eligibleUserIds);
|
|
$audits->whereIn('user_id', $eligibleUserIds);
|
|
}
|
|
|
|
return view('system_settings.dingtalk_bindings.index', [
|
|
'bindingRequests' => $bindingRequests->latest('last_attempted_at')->get(),
|
|
'identities' => $identities->latest('bound_at')->get(),
|
|
'eligibleUsers' => $eligibleUsers,
|
|
'audits' => $audits->latest('created_at')->limit(50)->get(),
|
|
]);
|
|
}
|
|
|
|
public function approve(DingTalkBindingRequest $bindingRequest, Request $request, DingTalkClosedAccess $access)
|
|
{
|
|
$data = $request->validate(['user_id' => ['required', 'integer']]);
|
|
$managedUser = $this->eligibleUsers()->findOrFail((int) $data['user_id']);
|
|
abort_unless(SystemAccess::canManageUser(user(), $managedUser) || $managedUser->id === user()->id, 403);
|
|
abort_unless(
|
|
SystemAccess::isSuperAdmin()
|
|
|| ((int) $bindingRequest->matched_user_id === (int) $managedUser->id),
|
|
403
|
|
);
|
|
|
|
if (DingTalkIdentity::query()->where('union_id', $bindingRequest->union_id)->exists()) {
|
|
throw ValidationException::withMessages(['binding' => '该钉钉账号已经完成绑定。']);
|
|
}
|
|
if (DingTalkIdentity::query()->where('user_id', $managedUser->id)->exists()) {
|
|
throw ValidationException::withMessages(['user_id' => '该财务账号已经绑定其他钉钉账号。']);
|
|
}
|
|
|
|
DB::transaction(function () use ($bindingRequest, $managedUser, $request, $access): void {
|
|
DingTalkIdentity::query()->create([
|
|
'user_id' => $managedUser->id,
|
|
'union_id' => $bindingRequest->union_id,
|
|
'open_id' => $bindingRequest->open_id,
|
|
'dingtalk_user_id' => $bindingRequest->dingtalk_user_id,
|
|
'nickname' => $bindingRequest->nickname,
|
|
'bound_by' => user()->id,
|
|
'bound_at' => now(),
|
|
]);
|
|
|
|
$bindingRequest->forceFill([
|
|
'status' => DingTalkBindingRequest::APPROVED,
|
|
'matched_user_id' => $managedUser->id,
|
|
'match_reason' => 'administrator_approved',
|
|
'reviewed_by' => user()->id,
|
|
'reviewed_at' => now(),
|
|
])->save();
|
|
|
|
$access->audit('binding_admin_approved', 'success', $managedUser->id, user()->id, $bindingRequest->union_id, $request);
|
|
});
|
|
|
|
flash('钉钉账号已绑定。')->success();
|
|
|
|
return redirect()->route('system-settings.dingtalk-bindings.index');
|
|
}
|
|
|
|
public function reject(DingTalkBindingRequest $bindingRequest, Request $request, DingTalkClosedAccess $access)
|
|
{
|
|
abort_unless(
|
|
SystemAccess::isSuperAdmin()
|
|
|| ($bindingRequest->matchedUser && SystemAccess::canManageUser(user(), $bindingRequest->matchedUser)),
|
|
403
|
|
);
|
|
abort_if(DingTalkIdentity::query()->where('union_id', $bindingRequest->union_id)->exists(), 422, '已绑定身份不能直接拒绝。');
|
|
|
|
$bindingRequest->forceFill([
|
|
'status' => DingTalkBindingRequest::REJECTED,
|
|
'matched_user_id' => null,
|
|
'match_reason' => 'administrator_rejected',
|
|
'reviewed_by' => user()->id,
|
|
'reviewed_at' => now(),
|
|
])->save();
|
|
$access->audit('binding_rejected', 'denied', null, user()->id, $bindingRequest->union_id, $request);
|
|
|
|
flash('钉钉绑定申请已拒绝。')->success();
|
|
|
|
return redirect()->route('system-settings.dingtalk-bindings.index');
|
|
}
|
|
|
|
public function destroy(DingTalkIdentity $identity, Request $request, DingTalkClosedAccess $access)
|
|
{
|
|
$managedUser = $identity->user()->firstOrFail();
|
|
abort_unless(SystemAccess::canManageUser(user(), $managedUser) || $managedUser->id === user()->id, 403);
|
|
|
|
DB::transaction(function () use ($identity, $managedUser, $request, $access): void {
|
|
$unionId = $identity->union_id;
|
|
$identity->delete();
|
|
DingTalkBindingRequest::query()->where('union_id', $unionId)->update([
|
|
'status' => DingTalkBindingRequest::REVOKED,
|
|
'match_reason' => 'administrator_revoked',
|
|
'reviewed_by' => user()->id,
|
|
'reviewed_at' => now(),
|
|
]);
|
|
$access->audit('binding_revoked', 'success', $managedUser->id, user()->id, $unionId, $request);
|
|
});
|
|
|
|
flash('钉钉账号绑定已解除。')->success();
|
|
|
|
return redirect()->route('system-settings.dingtalk-bindings.index');
|
|
}
|
|
|
|
private function eligibleUsers()
|
|
{
|
|
$query = User::query()
|
|
->where('enabled', true)
|
|
->whereHas('companies', fn ($company) => $company->where('companies.id', company_id())->where('companies.enabled', true));
|
|
|
|
if (! SystemAccess::isSuperAdmin()) {
|
|
$query->whereHas('roles', fn ($roles) => $roles->where('roles.name', SystemAccess::USER));
|
|
}
|
|
|
|
return $query;
|
|
}
|
|
}
|