hyperf-view/app/System/Service/SystemUserService.php

386 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace App\System\Service;
use App\System\Mapper\SystemUserMapper;
use Hyperf\Cache\Annotation\Cacheable;
use Hyperf\Cache\Annotation\CacheEvict;
use Hyperf\Contract\ContainerInterface;
use Hyperf\Di\Annotation\Inject;
use Builder\Abstracts\AbstractService;
use Builder\Event\UserAdd;
use Builder\Event\UserDelete;
use Builder\Exception\MineException;
use Builder\Exception\NormalStatusException;
use Builder\Helper\MineCaptcha;
use Builder\MineRequest;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\SimpleCache\CacheInterface;
use Psr\SimpleCache\InvalidArgumentException;
/**
* 用户业务
* Class SystemUserService
* @package App\System\Service
*/
class SystemUserService extends AbstractService
{
/**
* @var MineRequest
*/
#[Inject]
protected MineRequest $request;
/**
* @var ContainerInterface
*/
protected ContainerInterface $container;
/**
* @var SystemMenuService
*/
protected SystemMenuService $sysMenuService;
/**
* @var SystemRoleService
*/
protected SystemRoleService $sysRoleService;
/**
* @var SystemUserMapper
*/
public $mapper;
/**
* SystemUserService constructor.
* @param ContainerInterface $container
* @param SystemUserMapper $mapper
* @param SystemMenuService $systemMenuService
* @param SystemRoleService $systemRoleService
*/
public function __construct(
ContainerInterface $container,
SystemUserMapper $mapper,
SystemMenuService $systemMenuService,
SystemRoleService $systemRoleService
)
{
$this->mapper = $mapper;
$this->sysMenuService = $systemMenuService;
$this->sysRoleService = $systemRoleService;
$this->container = $container;
}
/**
* 获取验证码
* @return string
* @throws InvalidArgumentException
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function getCaptcha(): string
{
$cache = container()->get(CacheInterface::class);
$captcha = new MineCaptcha();
$info = $captcha->getCaptchaInfo();
$key = $this->request->ip() .'-'. \Builder\Helper\Str::lower($info['code']);
$cache->set(sprintf('captcha:%s', $key), $info['code'], 60);
return $info['image'];
}
/**
* 获取用户信息
* @return array
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function getInfo(): array
{
if ( ($uid = user()->getId()) ) {
return $this->getCacheInfo((int) $uid);
}
throw new MineException(t('system.unable_get_userinfo'), 500);
}
/**
* 获取缓存用户信息
* @param int $id
* @return array
*/
#[Cacheable(prefix: "loginInfo", ttl: 0, value: "userId_#{id}")]
protected function getCacheInfo(int $id): array
{
$user = $this->mapper->getModel()->find($id);
$user->addHidden('deleted_at', 'password');
$data['user'] = $user->toArray();
if (user()->isSuperAdmin()) {
$data['roles'] = ['superAdmin'];
$data['routers'] = $this->sysMenuService->mapper->getSuperAdminRouters();
$data['codes'] = ['*'];
} else {
$roles = $this->sysRoleService->mapper->getMenuIdsByRoleIds($user->roles()->pluck('id')->toArray());
$ids = $this->filterMenuIds($roles);
$data['roles'] = $user->roles()->pluck('code')->toArray();
$data['routers'] = $this->sysMenuService->mapper->getRoutersByIds($ids);
$data['codes'] = $this->sysMenuService->mapper->getMenuCode($ids);
}
return $data;
}
/**
* 过滤通过角色查询出来的菜单id列表并去重
* @param array $roleData
* @return array
*/
protected function filterMenuIds(array &$roleData): array
{
$ids = [];
foreach ($roleData as $val) {
foreach ($val['menus'] as $menu) {
$ids[] = $menu['id'];
}
}
unset($roleData);
return array_unique($ids);
}
/**
* 新增用户
* @param array $data
* @return int
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function save(array $data): int
{
if ($this->mapper->existsByUsername($data['username'])) {
throw new NormalStatusException(t('system.username_exists'));
} else {
$id = $this->mapper->save($this->handleData($data));
$data['id'] = $id;
event(new UserAdd($data));
return $id;
}
}
/**
* 更新用户信息
* @param int $id
* @param array $data
* @return bool
*/
#[CacheEvict(prefix: "loginInfo", value: "userId_#{id}")]
public function update(int $id, array $data): bool
{
if (isset($data['username'])) unset($data['username']);
if (isset($data['password'])) unset($data['password']);
return $this->mapper->update($id, $this->handleData($data));
}
/**
* 处理提交数据
* @param $data
* @return array
*/
protected function handleData($data): array
{
if (!is_array($data['role_ids'])) {
$data['role_ids'] = explode(',', $data['role_ids']);
}
if (($key = array_search(env('ADMIN_ROLE'), $data['role_ids'])) !== false) {
unset($data['role_ids'][$key]);
}
if (!empty($data['post_ids']) && !is_array($data['post_ids'])) {
$data['post_ids'] = explode(',', $data['post_ids']);
}
if (!empty($data['dept_ids']) && !is_array($data['dept_ids'])) {
$data['dept_ids'] = explode(',', $data['dept_ids']);
}
return $data;
}
/**
* 获取在线用户
* @param array $params
* @return array
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function getOnlineUserPageList(array $params = []): array
{
$redis = redis();
$key = sprintf('%sToken:*', config('cache.default.prefix'));
$userIds = [];
$iterator = null;
while (false !== ($users = $redis->scan($iterator, $key, 100))) {
foreach ($users as $user) {
if ( preg_match("/{$key}(\d+)$/", $user, $match) && isset($match[1])) {
$userIds[] = $match[1];
}
}
unset($users);
}
if (empty($userIds)) {
return [];
}
return $this->getPageList(array_merge(['userIds' => $userIds ], $params));
}
/**
* 删除用户
* @param array $ids
* @return bool
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function delete(array $ids): bool
{
if (!empty($ids)) {
if (($key = array_search(env('SUPER_ADMIN'), $ids)) !== false) {
unset($ids[$key]);
}
$result = $this->mapper->delete($ids);
event(new UserDelete($ids));
return $result;
}
return false;
}
/**
* 真实删除用户
* @param array $ids
* @return bool
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function realDelete(array $ids): bool
{
if (!empty($ids)) {
if (($key = array_search(env('SUPER_ADMIN'), $ids)) !== false) {
unset($ids[$key]);
}
$result = $this->mapper->realDelete($ids);
event(new UserDelete($ids));
return $result;
}
return false;
}
/**
* 强制下线用户
* @param string $id
* @return bool
* @throws InvalidArgumentException
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function kickUser(string $id): bool
{
$redis = redis();
$key = sprintf("%sToken:%s", config('cache.default.prefix'), $id);
user()->getJwt()->logout($redis->get($key), 'default');
$redis->del($key);
return true;
}
/**
* 初始化用户密码
* @param int $id
* @param string $password
* @return bool
*/
public function initUserPassword(int $id, string $password = '123456'): bool
{
return $this->mapper->initUserPassword($id, $password);
}
/**
* 清除用户缓存
* @param string $id
* @return bool
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function clearCache(string $id): bool
{
$redis = redis();
$prefix = config('cache.default.prefix');
$iterator = null;
while (false !== ($configKey = $redis->scan($iterator, $prefix . 'config:*', 100))) {
$redis->del($configKey);
}
while (false !== ($dictKey = $redis->scan($iterator, $prefix . 'Dict:*', 100))) {
$redis->del($dictKey);
}
$redis->del([$prefix . 'crontab', $prefix . 'modules']);
return $redis->del("{$prefix}loginInfo:userId_{$id}") > 0;
}
/**
* 设置用户首页
* @param array $params
* @return bool
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function setHomePage(array $params): bool
{
$res = ($this->mapper->getModel())::query()
->where('id', $params['id'])
->update(['dashboard' => $params['dashboard']]) > 0;
$this->clearCache((string) $params['id']);
return $res;
}
/**
* 用户更新个人资料
* @param array $params
* @return bool
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function updateInfo(array $params): bool
{
if (!isset($params['id'])) {
return false;
}
$model = $this->mapper->getModel()::find($params['id']);
unset($params['id'], $params['password']);
foreach ($params as $key => $param) {
$model[$key] = $param;
}
$this->clearCache((string) $model['id']);
return $model->save();
}
/**
* 用户修改密码
* @param array $params
* @return bool
*/
public function modifyPassword(array $params): bool
{
return $this->mapper->initUserPassword((int) user()->getId(), $params['newPassword']);
}
/**
* 通过 id 列表获取用户基础信息
*/
public function getUserInfoByIds(array $ids): array
{
return $this->mapper->getUserInfoByIds($ids);
}
}