| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- <?php
- declare(strict_types=1);
- namespace app\miniapi\service;
- use app\miniapi\auth\Principal;
- use app\miniapi\auth\WechatIdentityProvider;
- use app\miniapi\auth\IdentityProvider;
- use app\miniapi\model\MiniUser;
- use app\miniapi\model\MiniSession;
- use app\miniapi\http\Fields;
- use app\miniapi\exception\ApiException;
- final class AuthService
- {
- public function __construct(private readonly IdentityProvider $provider = new WechatIdentityProvider())
- {
- }
- public function login(array $input): array
- {
- Fields::only($input, ['code']);
- $identity = $this->provider->exchange(Fields::text($input, 'code', 512));
- return $this->issue($identity);
- }
- /** Internal only. The HTTP controller never accepts provider identity from clients. */
- public function issue(array $identity): array
- {
- return (new MiniUser())->getConnection()->transaction(function () use ($identity) {
- $now = date('Y-m-d H:i:s');
- MiniUser::query()->insertOrIgnore($identity + [
- 'nickname' => '',
- 'status' => 1,
- 'created_at' => $now,
- 'updated_at' => $now,
- ]);
- $user = MiniUser::query()->where($identity)->lockForUpdate()->firstOrFail();
- if ((int) $user->status !== 1) {
- throw new ApiException(40302, '账号已停用', 403);
- }
- $token = bin2hex(random_bytes(32));
- $expires = date('Y-m-d H:i:s', time() + (int) config('mini_api.session_ttl', 604800));
- MiniSession::query()->insert([
- 'user_id' => $user->id,
- 'token_hash' => hash('sha256', $token),
- 'expires_at' => $expires,
- 'created_at' => $now,
- ]);
- return [
- 'access_token' => $token,
- 'token_type' => 'Bearer',
- 'expires_at' => $expires,
- 'user_id' => (string) $user->id,
- 'identities' => (new Access(new Principal((string) $user->id)))->identities(),
- ];
- });
- }
- public function logout(string $token): array
- {
- MiniSession::query()->where('token_hash', hash('sha256', $token))->whereNull('revoked_at')->update(['revoked_at' => date('Y-m-d H:i:s')]);
- return ['logged_out' => true];
- }
- }
|