更新
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\mcp\controller;
|
||||
|
||||
use app\BaseController;
|
||||
use app\mcp\service\AuditLogger;
|
||||
use app\mcp\service\Catalog;
|
||||
use app\mcp\service\GrantService;
|
||||
use app\mcp\service\Guard;
|
||||
use app\mcp\service\McpConfig;
|
||||
use app\mcp\service\McpException;
|
||||
use think\Response;
|
||||
|
||||
/**
|
||||
* AI 授权接口(供行知等客户端调用):
|
||||
* POST /mcp/auth/grant 账号 + 密码 → 只读令牌(密码只用于本次校验,不保存)
|
||||
* POST /mcp/auth/revoke 撤销当前令牌(Bearer)
|
||||
* GET /mcp/auth/whoami 当前令牌对应的账号(Bearer)
|
||||
*/
|
||||
class AuthController extends BaseController
|
||||
{
|
||||
public function grant(): Response
|
||||
{
|
||||
$blocked = $this->blocked('POST');
|
||||
if ($blocked) {
|
||||
return $blocked;
|
||||
}
|
||||
$input = json_decode((string) $this->request->getInput(), true);
|
||||
if (!is_array($input)) {
|
||||
$input = $this->request->post();
|
||||
}
|
||||
$ip = $this->request->ip();
|
||||
try {
|
||||
$data = GrantService::issue($input, $ip);
|
||||
AuditLogger::log(['grant_id' => $data['grant_id'], 'admin_id' => $data['admin']['id'], 'tool' => 'auth.grant',
|
||||
'arguments' => ['client' => $input['client'] ?? '', 'client_instance' => $input['client_instance'] ?? ''], 'status' => 'ok', 'ip' => $ip]);
|
||||
return Guard::envelope(1, '授权成功', $data);
|
||||
} catch (McpException $e) {
|
||||
AuditLogger::log(['tool' => 'auth.grant', 'arguments' => ['account' => (string) ($input['account'] ?? '')], 'status' => 'denied',
|
||||
'message' => $e->reason, 'ip' => $ip]);
|
||||
return Guard::envelope(0, $e->getMessage(), ['reason' => $e->reason], $e->httpStatus === 401 ? 200 : $e->httpStatus, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public function revoke(): Response
|
||||
{
|
||||
$blocked = $this->blocked('POST');
|
||||
if ($blocked) {
|
||||
return $blocked;
|
||||
}
|
||||
try {
|
||||
$identity = GrantService::authenticate($this->request);
|
||||
} catch (McpException $e) {
|
||||
return Guard::envelope(-1, $e->getMessage(), ['reason' => $e->reason], 401);
|
||||
}
|
||||
GrantService::close((int) $identity->grant['id'], GrantService::STATUS_REVOKED, 'client_revoke');
|
||||
AuditLogger::log(['grant_id' => $identity->grant['id'], 'admin_id' => $identity->adminId, 'tool' => 'auth.revoke', 'status' => 'ok', 'ip' => $this->request->ip()]);
|
||||
return Guard::envelope(1, '已撤销');
|
||||
}
|
||||
|
||||
public function whoami(): Response
|
||||
{
|
||||
$blocked = $this->blocked('GET');
|
||||
if ($blocked) {
|
||||
return $blocked;
|
||||
}
|
||||
try {
|
||||
$identity = GrantService::authenticate($this->request);
|
||||
} catch (McpException $e) {
|
||||
return Guard::envelope(-1, $e->getMessage(), ['reason' => $e->reason], 401);
|
||||
}
|
||||
return Guard::envelope(1, '', [
|
||||
'admin' => $identity->publicProfile(),
|
||||
'grant' => GrantService::publicGrant($identity->grant),
|
||||
'data_scope' => $identity->dataScopeText(),
|
||||
'resources' => ['open' => count(Catalog::openFor($identity))],
|
||||
]);
|
||||
}
|
||||
|
||||
private function blocked(string $method): ?Response
|
||||
{
|
||||
if (!McpConfig::enabled()) {
|
||||
return Guard::envelope(0, 'AI 助手接口未启用', ['reason' => 'feature_disabled'], 503, 1);
|
||||
}
|
||||
if ($this->request->method(true) !== $method) {
|
||||
return response('', 405)->header(['Allow' => $method]);
|
||||
}
|
||||
$guard = Guard::check($this->request);
|
||||
if ($guard !== null) {
|
||||
return Guard::envelope(0, $guard[1], ['reason' => $guard[2]], 200, 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user