feat: support user become app admin by username and passwor

This commit is contained in:
tjq 2024-02-18 19:56:51 +08:00
parent d1d0407046
commit a750d0c55c
5 changed files with 72 additions and 5 deletions

View File

@ -18,6 +18,15 @@ import java.util.Map;
*/ */
public interface WebAuthService { public interface WebAuthService {
/**
* 对当前登录用户授予角色
* @param roleScope 角色范围
* @param target 目标
* @param role 角色
* @param extra 其他信息
*/
void grantRole2LoginUser(RoleScope roleScope, Long target, Role role, String extra);
/** /**
* 处理授权 * 处理授权
* @param roleScope 权限范围 * @param roleScope 权限范围

View File

@ -29,6 +29,15 @@ public class WebAuthServiceImpl implements WebAuthService {
private PowerJobPermissionService powerJobPermissionService; private PowerJobPermissionService powerJobPermissionService;
@Override
public void grantRole2LoginUser(RoleScope roleScope, Long target, Role role, String extra) {
Long userId = LoginUserHolder.getUserId();
if (userId == null) {
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_LOGIN);
}
powerJobPermissionService.grantRole(roleScope, target, userId, role, extra);
}
@Override @Override
public void processPermissionOnSave(RoleScope roleScope, Long target, ComponentUserRoleInfo o) { public void processPermissionOnSave(RoleScope roleScope, Long target, ComponentUserRoleInfo o) {
ComponentUserRoleInfo componentUserRoleInfo = Optional.ofNullable(o).orElse(new ComponentUserRoleInfo()); ComponentUserRoleInfo componentUserRoleInfo = Optional.ofNullable(o).orElse(new ComponentUserRoleInfo());

View File

@ -1,6 +1,7 @@
package tech.powerjob.server.web.controller; package tech.powerjob.server.web.controller;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;
@ -13,11 +14,15 @@ import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import tech.powerjob.common.response.ResultDTO; import tech.powerjob.common.response.ResultDTO;
import tech.powerjob.common.serialize.JsonUtils;
import tech.powerjob.common.utils.CommonUtils; import tech.powerjob.common.utils.CommonUtils;
import tech.powerjob.server.auth.LoginUserHolder; import tech.powerjob.server.auth.LoginUserHolder;
import tech.powerjob.server.auth.Permission; import tech.powerjob.server.auth.Permission;
import tech.powerjob.server.auth.Role;
import tech.powerjob.server.auth.RoleScope; import tech.powerjob.server.auth.RoleScope;
import tech.powerjob.server.auth.common.AuthConstants; import tech.powerjob.server.auth.common.AuthConstants;
import tech.powerjob.server.auth.common.AuthErrorCode;
import tech.powerjob.server.auth.common.PowerJobAuthException;
import tech.powerjob.server.auth.interceptor.ApiPermission; import tech.powerjob.server.auth.interceptor.ApiPermission;
import tech.powerjob.server.auth.plugin.ModifyOrCreateDynamicPermission; import tech.powerjob.server.auth.plugin.ModifyOrCreateDynamicPermission;
import tech.powerjob.server.auth.plugin.SaveAppGrantPermissionPlugin; import tech.powerjob.server.auth.plugin.SaveAppGrantPermissionPlugin;
@ -28,6 +33,7 @@ import tech.powerjob.server.persistence.remote.model.AppInfoDO;
import tech.powerjob.server.persistence.remote.model.NamespaceDO; import tech.powerjob.server.persistence.remote.model.NamespaceDO;
import tech.powerjob.server.persistence.remote.repository.AppInfoRepository; import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
import tech.powerjob.server.web.converter.NamespaceConverter; import tech.powerjob.server.web.converter.NamespaceConverter;
import tech.powerjob.server.web.request.AppAssertRequest;
import tech.powerjob.server.web.request.ComponentUserRoleInfo; import tech.powerjob.server.web.request.ComponentUserRoleInfo;
import tech.powerjob.server.web.request.ModifyAppInfoRequest; import tech.powerjob.server.web.request.ModifyAppInfoRequest;
import tech.powerjob.server.web.request.QueryAppInfoRequest; import tech.powerjob.server.web.request.QueryAppInfoRequest;
@ -108,7 +114,7 @@ public class AppInfoController {
} }
@PostMapping("/list") @PostMapping("/list")
@ApiPermission(name = "Namespace-List", roleScope = RoleScope.APP, requiredPermission = Permission.NONE) @ApiPermission(name = "App-List", roleScope = RoleScope.APP, requiredPermission = Permission.NONE)
public ResultDTO<PageResult<AppInfoVO>> listAppInfoByQuery(@RequestBody QueryAppInfoRequest queryAppInfoRequest) { public ResultDTO<PageResult<AppInfoVO>> listAppInfoByQuery(@RequestBody QueryAppInfoRequest queryAppInfoRequest) {
Pageable pageable = PageRequest.of(queryAppInfoRequest.getIndex(), queryAppInfoRequest.getPageSize()); Pageable pageable = PageRequest.of(queryAppInfoRequest.getIndex(), queryAppInfoRequest.getPageSize());
@ -163,6 +169,26 @@ public class AppInfoController {
return ResultDTO.success(pageRet); return ResultDTO.success(pageRet);
} }
@PostMapping("/becomeAdmin")
@ApiPermission(name = "App-BecomeAdmin", roleScope = RoleScope.GLOBAL, requiredPermission = Permission.NONE)
public ResultDTO<Void> becomeAdminByAppNameAndPassword(@RequestBody AppAssertRequest appAssertRequest) {
String appName = appAssertRequest.getAppName();
Optional<AppInfoDO> appInfoOpt = appInfoRepository.findByAppName(appName);
if (!appInfoOpt.isPresent()) {
throw new IllegalArgumentException("can't find app by appName: " + appName);
}
if (!StringUtils.equals(appInfoOpt.get().getPassword(), appAssertRequest.getPassword())) {
throw new PowerJobAuthException(AuthErrorCode.INCORRECT_PASSWORD);
}
Map<String, Object> extra = Maps.newHashMap();
extra.put("source", "becomeAdminByAppNameAndPassword");
webAuthService.grantRole2LoginUser(RoleScope.APP, appInfoOpt.get().getId(), Role.ADMIN, JsonUtils.toJSONString(extra));
return ResultDTO.success(null);
}
private List<AppInfoVO> convert(List<AppInfoDO> data, boolean fillDetail) { private List<AppInfoVO> convert(List<AppInfoDO> data, boolean fillDetail) {
if (CollectionUtils.isEmpty(data)) { if (CollectionUtils.isEmpty(data)) {
return Lists.newLinkedList(); return Lists.newLinkedList();

View File

@ -105,8 +105,8 @@ public class AuthController {
} }
@PostMapping("/saveGlobalAdmin") @PostMapping("/saveGlobalAdmin")
@ApiPermission(name = "Auth-GrantAdmin", roleScope = RoleScope.GLOBAL, requiredPermission = Permission.SU) @ApiPermission(name = "Auth-SaveGlobalAdmin", roleScope = RoleScope.GLOBAL, requiredPermission = Permission.SU)
public ResultDTO<Void> grantAppPermission(@RequestBody ComponentUserRoleInfo componentUserRoleInfo) { public ResultDTO<Void> saveGlobalAdmin(@RequestBody ComponentUserRoleInfo componentUserRoleInfo) {
if (CollectionUtils.isEmpty(componentUserRoleInfo.getAdmin())) { if (CollectionUtils.isEmpty(componentUserRoleInfo.getAdmin())) {
throw new IllegalArgumentException("At least one super administrator is required!"); throw new IllegalArgumentException("At least one super administrator is required!");

View File

@ -1,5 +1,7 @@
package tech.powerjob.server.web.service.impl; package tech.powerjob.server.web.service.impl;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import tech.powerjob.server.persistence.remote.model.UserInfoDO; import tech.powerjob.server.persistence.remote.model.UserInfoDO;
import tech.powerjob.server.persistence.remote.repository.UserInfoRepository; import tech.powerjob.server.persistence.remote.repository.UserInfoRepository;
@ -9,6 +11,7 @@ import tech.powerjob.server.web.service.UserWebService;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.TimeUnit;
/** /**
* UserWebService * UserWebService
@ -19,6 +22,15 @@ import java.util.Optional;
@Service @Service
public class UserWebServiceImpl implements UserWebService { public class UserWebServiceImpl implements UserWebService {
/**
* 展示用的 user 查询缓存对延迟不敏感
*/
private final Cache<Long, UserInfoDO> userCache4Show = CacheBuilder.newBuilder()
.softValues()
.maximumSize(256)
.expireAfterWrite(3, TimeUnit.MINUTES)
.build();
@Resource @Resource
private UserInfoRepository userInfoRepository; private UserInfoRepository userInfoRepository;
@ -29,7 +41,18 @@ public class UserWebServiceImpl implements UserWebService {
return Optional.empty(); return Optional.empty();
} }
Optional<UserInfoDO> userInfoOpt = userInfoRepository.findById(userId); try {
return userInfoOpt.map(UserConverter::do2BaseVo); UserInfoDO userInfoDO = userCache4Show.get(userId, () -> {
Optional<UserInfoDO> userInfoOpt = userInfoRepository.findById(userId);
if (userInfoOpt.isPresent()) {
return userInfoOpt.get();
}
throw new IllegalArgumentException("can't find user by userId: " + userId);
});
return Optional.of(UserConverter.do2BaseVo(userInfoDO));
} catch (Exception e) {
return Optional.empty();
}
} }
} }