| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- <?php
- declare(strict_types=1);
- namespace app\miniapi\service;
- use app\miniapi\model\MiniUser;
- use app\miniapi\model\MiniGrant;
- use app\miniapi\http\Fields;
- use app\miniapi\http\Input;
- use app\miniapi\http\Pagination;
- use app\miniapi\support\PhoneNumber;
- use app\miniapi\exception\ApiException;
- use plugin\saiadmin\app\model\water\WaterOperator;
- final class IdentityManagement
- {
- private function authorize(int $admin): void
- {
- if ($admin !== 1 || !WaterOperator::query()->where('id', $admin)->where('status', 1)->whereNull('delete_time')->exists()) {
- throw new ApiException(40301, '仅超级管理员可管理小程序身份', 403);
- }
- }
- public function users(int $admin, array $input): array
- {
- $this->authorize($admin);
- $page = new Pagination($input);
- $q = MiniUser::query();
- if (isset($input['user_id'])) {
- $q->where('id', Fields::id($input, 'user_id'));
- }
- $total = (clone $q)->count();
- return $page->result($q->orderByDesc('id')->offset($page->offset())->limit($page->pageSize)->get()->map(function ($u) {
- return [
- 'id' => (int) $u->id,
- 'nickname' => $u->nickname,
- 'phone' => PhoneNumber::mask((string) ($u->phone ?? '')),
- 'status' => (int) $u->status,
- 'created_at' => $u->created_at,
- 'grants' => MiniGrant::query()->where('user_id', $u->id)->get([
- 'id',
- 'role',
- 'resource_id',
- 'status',
- ])->toArray(),
- ];
- })->all(), $total);
- }
- public function grant(int $admin, array $input): array
- {
- $this->authorize($admin);
- Fields::only($input, [
- 'user_id',
- 'role',
- 'resource_id',
- 'status',
- ]);
- $user = Fields::id($input, 'user_id');
- $role = Fields::choice($input, 'role', Access::roles());
- $resource = Fields::id($input, 'resource_id');
- $status = Input::integer($input['status'] ?? 1, 'status', 0, 1);
- return (new MiniUser())->getConnection()->transaction(function () use ($admin, $user, $role, $resource, $status) {
- if (!MiniUser::query()->where('id', $user)->lockForUpdate()->first()) {
- throw new ApiException(40401, '小程序用户不存在', 404);
- }
- if ($status === 1 && MiniGrant::query()->where('user_id', $user)->where('status', 1)
- ->where(function ($query) use ($role, $resource) {
- $query->where('role', '!=', $role)->orWhere('resource_id', '!=', $resource);
- })->exists()) {
- throw new ApiException(40903, '一个小程序账号只能绑定一个业务身份,请先停用原身份', 409);
- }
- $model = Access::resourceModel($role);
- if (!$model::query()->where('id', $resource)->exists()) {
- throw new ApiException(40401, '业务档案不存在', 404);
- }
- $row = MiniGrant::query()->updateOrCreate(
- [
- 'user_id' => $user,
- 'role' => $role,
- 'resource_id' => $resource,
- ],
- [
- 'status' => $status,
- 'created_by' => $admin,
- 'created_at' => date('Y-m-d H:i:s'),
- 'updated_at' => date('Y-m-d H:i:s'),
- ]
- );
- Commands::audit('admin', $admin, 'identity.grant', (int) $row->id, [
- 'user_id' => $user,
- 'role' => $role,
- 'resource_id' => $resource,
- 'status' => $status,
- ]);
- return [
- 'id' => (int) $row->id,
- 'status' => $status,
- ];
- });
- }
- /**
- * Binds a phone to an existing account so SMS login reaches the same user and therefore the
- * same granted identity. This never creates an account and never changes a grant.
- */
- public function bindPhone(int $admin, array $input): array
- {
- $this->authorize($admin);
- Fields::only($input, [
- 'user_id',
- 'phone',
- ]);
- $user = Fields::id($input, 'user_id');
- $phone = SmsLogin::mobile($input);
- return (new MiniUser())->getConnection()->transaction(function () use ($admin, $user, $phone) {
- if (!MiniUser::query()->where('id', $user)->lockForUpdate()->first()) {
- throw new ApiException(40401, '小程序用户不存在', 404);
- }
- if (MiniUser::query()->where('phone', $phone)->where('id', '!=', $user)->lockForUpdate()->exists()) {
- throw new ApiException(40903, '该手机号已绑定其他小程序账号,请先解绑', 409);
- }
- MiniUser::query()->where('id', $user)->update([
- 'phone' => $phone,
- 'updated_at' => date('Y-m-d H:i:s'),
- ]);
- Commands::audit('admin', $admin, 'identity.bind_phone', $user, [
- 'user_id' => $user,
- 'phone' => PhoneNumber::mask($phone),
- ]);
- return [
- 'user_id' => $user,
- 'phone' => PhoneNumber::mask($phone),
- ];
- });
- }
- }
|