[Improvement-13824][Resource Center] User can only visit resources under tenant defaultPath (#13848)
* [Improvement-13824][Resource Center] User can only visit resources under tenant defaultPath * remove semicolon * set null in some specific scenario * remove useless console.log
This commit is contained in:
parent
51afbfe159
commit
4bf097ee40
|
|
@ -772,4 +772,17 @@ public class ResourcesController extends BaseController {
|
||||||
|
|
||||||
return resourceService.queryResourceByFullName(loginUser, fullName, tenantCode, type);
|
return resourceService.queryResourceByFullName(loginUser, fullName, tenantCode, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "queryResourceBaseDir", description = "QUERY_RESOURCE_BASE_DIR")
|
||||||
|
@Parameters({
|
||||||
|
@Parameter(name = "type", description = "RESOURCE_TYPE", required = true, schema = @Schema(implementation = ResourceType.class))
|
||||||
|
})
|
||||||
|
@GetMapping(value = "/base-dir")
|
||||||
|
@ResponseStatus(HttpStatus.OK)
|
||||||
|
@ApiException(RESOURCE_NOT_EXIST)
|
||||||
|
@AccessLogAnnotation
|
||||||
|
public Result<Object> queryResourceBaseDir(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||||
|
@RequestParam(value = "type") ResourceType type) {
|
||||||
|
return resourceService.queryResourceBaseDir(loginUser, type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -271,4 +271,13 @@ public interface ResourcesService {
|
||||||
Result<Object> queryResourceByFullName(User loginUser, String fullName, String tenantCode,
|
Result<Object> queryResourceByFullName(User loginUser, String fullName, String tenantCode,
|
||||||
ResourceType type) throws IOException;
|
ResourceType type) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get resource base dir
|
||||||
|
*
|
||||||
|
* @param loginUser login user
|
||||||
|
* @param type resource type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Result<Object> queryResourceBaseDir(User loginUser, ResourceType type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -574,8 +574,10 @@ public class ResourcesServiceImpl extends BaseServiceImpl implements ResourcesSe
|
||||||
}
|
}
|
||||||
|
|
||||||
String tenantCode = getTenantCode(user);
|
String tenantCode = getTenantCode(user);
|
||||||
|
String baseDir = isAdmin(loginUser) ? storageOperate.getDir(ResourceType.ALL, tenantCode)
|
||||||
if (!isUserTenantValid(isAdmin(loginUser), tenantCode, resTenantCode)) {
|
: storageOperate.getDir(type, tenantCode);
|
||||||
|
if (!isUserTenantValid(isAdmin(loginUser), tenantCode, resTenantCode)
|
||||||
|
|| (StringUtils.isNotBlank(fullName) && !StringUtils.startsWith(fullName, baseDir))) {
|
||||||
log.error("current user does not have permission");
|
log.error("current user does not have permission");
|
||||||
putMsg(result, Status.NO_CURRENT_OPERATING_PERMISSION);
|
putMsg(result, Status.NO_CURRENT_OPERATING_PERMISSION);
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1679,6 +1681,40 @@ public class ResourcesServiceImpl extends BaseServiceImpl implements ResourcesSe
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get resource base dir
|
||||||
|
*
|
||||||
|
* @param loginUser login user
|
||||||
|
* @param type resource type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Result<Object> queryResourceBaseDir(User loginUser, ResourceType type) {
|
||||||
|
Result<Object> result = new Result<>();
|
||||||
|
User user = userMapper.selectById(loginUser.getId());
|
||||||
|
if (user == null) {
|
||||||
|
log.error("user {} not exists", loginUser.getId());
|
||||||
|
putMsg(result, Status.USER_NOT_EXIST, loginUser.getId());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String tenantCode = getTenantCode(user);
|
||||||
|
|
||||||
|
if (!isUserTenantValid(isAdmin(loginUser), tenantCode, "")) {
|
||||||
|
log.error("current user does not have permission");
|
||||||
|
putMsg(result, Status.NO_CURRENT_OPERATING_PERMISSION);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String baseDir = isAdmin(loginUser) ? storageOperate.getDir(ResourceType.ALL, tenantCode)
|
||||||
|
: storageOperate.getDir(type, tenantCode);
|
||||||
|
|
||||||
|
putMsg(result, Status.SUCCESS);
|
||||||
|
result.setData(baseDir);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get authorized resource list
|
* get authorized resource list
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -892,6 +892,24 @@ public class ResourcesServiceTest {
|
||||||
logger.error("hadoop error", e);
|
logger.error("hadoop error", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueryBaseDir() {
|
||||||
|
User user = getUser();
|
||||||
|
Mockito.when(userMapper.selectById(user.getId())).thenReturn(getUser());
|
||||||
|
Mockito.when(tenantMapper.queryById(user.getTenantId())).thenReturn(getTenant());
|
||||||
|
Mockito.when(storageOperate.getDir(ResourceType.FILE, "123")).thenReturn("/dolphinscheduler/123/resources/");
|
||||||
|
try {
|
||||||
|
Mockito.when(storageOperate.getFileStatus(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(),
|
||||||
|
Mockito.any())).thenReturn(getStorageEntityResource());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e.getMessage() + " Resource path: {}", "/dolphinscheduler/123/resources/ResourcesServiceTest",
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
Result<Object> result = resourcesService.queryResourceBaseDir(user, ResourceType.FILE);
|
||||||
|
Assertions.assertEquals(Status.SUCCESS.getMsg(), result.getMsg());
|
||||||
|
}
|
||||||
|
|
||||||
private List<Resource> getResourceList() {
|
private List<Resource> getResourceList() {
|
||||||
|
|
||||||
List<Resource> resources = new ArrayList<>();
|
List<Resource> resources = new ArrayList<>();
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ public enum ResourceType {
|
||||||
* 0 file, 1 udf
|
* 0 file, 1 udf
|
||||||
*/
|
*/
|
||||||
FILE(0, "file"),
|
FILE(0, "file"),
|
||||||
UDF(1, "udf");
|
UDF(1, "udf"),
|
||||||
|
ALL(2, "all");
|
||||||
|
|
||||||
ResourceType(int code, String descp) {
|
ResourceType(int code, String descp) {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@ public interface StorageOperate {
|
||||||
* @param tenantCode
|
* @param tenantCode
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|
||||||
String getUdfDir(String tenantCode);
|
String getUdfDir(String tenantCode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -252,6 +252,8 @@ public class GcsStorageOperator implements Closeable, StorageOperate {
|
||||||
return getUdfDir(tenantCode);
|
return getUdfDir(tenantCode);
|
||||||
case FILE:
|
case FILE:
|
||||||
return getResDir(tenantCode);
|
return getResDir(tenantCode);
|
||||||
|
case ALL:
|
||||||
|
return getGcsDataBasePath();
|
||||||
default:
|
default:
|
||||||
return EMPTY_STRING;
|
return EMPTY_STRING;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.plugin.storage.hdfs;
|
package org.apache.dolphinscheduler.plugin.storage.hdfs;
|
||||||
|
|
||||||
|
import static org.apache.dolphinscheduler.common.constants.Constants.EMPTY_STRING;
|
||||||
import static org.apache.dolphinscheduler.common.constants.Constants.FOLDER_SEPARATOR;
|
import static org.apache.dolphinscheduler.common.constants.Constants.FOLDER_SEPARATOR;
|
||||||
import static org.apache.dolphinscheduler.common.constants.Constants.FORMAT_S_S;
|
import static org.apache.dolphinscheduler.common.constants.Constants.FORMAT_S_S;
|
||||||
import static org.apache.dolphinscheduler.common.constants.Constants.RESOURCE_TYPE_FILE;
|
import static org.apache.dolphinscheduler.common.constants.Constants.RESOURCE_TYPE_FILE;
|
||||||
|
|
@ -615,13 +616,16 @@ public class HdfsStorageOperator implements Closeable, StorageOperate {
|
||||||
* @return hdfs resource dir
|
* @return hdfs resource dir
|
||||||
*/
|
*/
|
||||||
public static String getHdfsDir(ResourceType resourceType, String tenantCode) {
|
public static String getHdfsDir(ResourceType resourceType, String tenantCode) {
|
||||||
String hdfsDir = "";
|
switch (resourceType) {
|
||||||
if (resourceType.equals(ResourceType.FILE)) {
|
case UDF:
|
||||||
hdfsDir = getHdfsResDir(tenantCode);
|
return getHdfsUdfDir(tenantCode);
|
||||||
} else if (resourceType.equals(ResourceType.UDF)) {
|
case FILE:
|
||||||
hdfsDir = getHdfsUdfDir(tenantCode);
|
return getHdfsResDir(tenantCode);
|
||||||
|
case ALL:
|
||||||
|
return getHdfsDataBasePath();
|
||||||
|
default:
|
||||||
|
return EMPTY_STRING;
|
||||||
}
|
}
|
||||||
return hdfsDir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,8 @@ public class OssStorageOperator implements Closeable, StorageOperate {
|
||||||
return getUdfDir(tenantCode);
|
return getUdfDir(tenantCode);
|
||||||
case FILE:
|
case FILE:
|
||||||
return getResDir(tenantCode);
|
return getResDir(tenantCode);
|
||||||
|
case ALL:
|
||||||
|
return getOssDataBasePath();
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -290,6 +290,8 @@ public class S3StorageOperator implements Closeable, StorageOperate {
|
||||||
return getUdfDir(tenantCode);
|
return getUdfDir(tenantCode);
|
||||||
case FILE:
|
case FILE:
|
||||||
return getResDir(tenantCode);
|
return getResDir(tenantCode);
|
||||||
|
case ALL:
|
||||||
|
return getS3DataBasePath();
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ export function useDropDown() {
|
||||||
userStore.setSessionId('')
|
userStore.setSessionId('')
|
||||||
userStore.setSecurityConfigType('')
|
userStore.setSecurityConfigType('')
|
||||||
userStore.setUserInfo({})
|
userStore.setUserInfo({})
|
||||||
|
userStore.setBaseResDir('')
|
||||||
|
userStore.setBaseUdfDir('')
|
||||||
cookies.remove('sessionId')
|
cookies.remove('sessionId')
|
||||||
|
|
||||||
router.push({ path: '/login' })
|
router.push({ path: '/login' })
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,16 @@ export function queryResourceListPaging(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function queryBaseDir(
|
||||||
|
params: ResourceTypeReq
|
||||||
|
): any {
|
||||||
|
return axios({
|
||||||
|
url: '/resources/base-dir',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export function queryCurrentResourceByFileName(
|
export function queryCurrentResourceByFileName(
|
||||||
params: ResourceTypeReq & FileNameReq & TenantCodeReq,
|
params: ResourceTypeReq & FileNameReq & TenantCodeReq,
|
||||||
): any {
|
): any {
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ const err = (err: AxiosError): Promise<AxiosError> => {
|
||||||
userStore.setSessionId('')
|
userStore.setSessionId('')
|
||||||
userStore.setSecurityConfigType('')
|
userStore.setSecurityConfigType('')
|
||||||
userStore.setUserInfo({})
|
userStore.setUserInfo({})
|
||||||
|
userStore.setBaseResDir('')
|
||||||
|
userStore.setBaseUdfDir('')
|
||||||
router.push({ path: '/login' })
|
router.push({ path: '/login' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ import type { UserInfoRes } from '@/service/modules/users/types'
|
||||||
interface UserState {
|
interface UserState {
|
||||||
sessionId: string
|
sessionId: string
|
||||||
securityConfigType: string
|
securityConfigType: string
|
||||||
|
baseResDir: string
|
||||||
|
baseUdfDir: string
|
||||||
userInfo: UserInfoRes | {}
|
userInfo: UserInfoRes | {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ export const useUserStore = defineStore({
|
||||||
state: (): UserState => ({
|
state: (): UserState => ({
|
||||||
sessionId: '',
|
sessionId: '',
|
||||||
securityConfigType: '',
|
securityConfigType: '',
|
||||||
|
baseResDir: '',
|
||||||
|
baseUdfDir: '',
|
||||||
userInfo: {}
|
userInfo: {}
|
||||||
}),
|
}),
|
||||||
persist: true,
|
persist: true,
|
||||||
|
|
@ -36,6 +38,12 @@ export const useUserStore = defineStore({
|
||||||
},
|
},
|
||||||
getUserInfo(): UserInfoRes | {} {
|
getUserInfo(): UserInfoRes | {} {
|
||||||
return this.userInfo
|
return this.userInfo
|
||||||
|
},
|
||||||
|
getBaseResDir(): string {
|
||||||
|
return this.baseResDir
|
||||||
|
},
|
||||||
|
getBaseUdfDir(): string {
|
||||||
|
return this.baseUdfDir
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
|
@ -47,6 +55,12 @@ export const useUserStore = defineStore({
|
||||||
},
|
},
|
||||||
setUserInfo(userInfo: UserInfoRes | {}): void {
|
setUserInfo(userInfo: UserInfoRes | {}): void {
|
||||||
this.userInfo = userInfo
|
this.userInfo = userInfo
|
||||||
|
},
|
||||||
|
setBaseResDir(baseResDir: string): void {
|
||||||
|
this.baseResDir = baseResDir
|
||||||
|
},
|
||||||
|
setBaseUdfDir(baseUdfDir: string): void {
|
||||||
|
this.baseUdfDir = baseUdfDir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import type { UserInfoRes } from '@/service/modules/users/types'
|
||||||
import { useRouteStore } from '@/store/route/route'
|
import { useRouteStore } from '@/store/route/route'
|
||||||
import { useTimezoneStore } from '@/store/timezone/timezone'
|
import { useTimezoneStore } from '@/store/timezone/timezone'
|
||||||
import cookies from 'js-cookie'
|
import cookies from 'js-cookie'
|
||||||
|
import {queryBaseDir} from "@/service/modules/resources";
|
||||||
|
|
||||||
export function useLogin(state: any) {
|
export function useLogin(state: any) {
|
||||||
const router: Router = useRouter()
|
const router: Router = useRouter()
|
||||||
|
|
@ -43,6 +44,15 @@ export function useLogin(state: any) {
|
||||||
const userInfoRes: UserInfoRes = await getUserInfo()
|
const userInfoRes: UserInfoRes = await getUserInfo()
|
||||||
await userStore.setUserInfo(userInfoRes)
|
await userStore.setUserInfo(userInfoRes)
|
||||||
|
|
||||||
|
const baseResDir = await queryBaseDir({
|
||||||
|
type: 'FILE'
|
||||||
|
})
|
||||||
|
const baseUdfDir = await queryBaseDir({
|
||||||
|
type: 'UDF'
|
||||||
|
})
|
||||||
|
await userStore.setBaseResDir(baseResDir)
|
||||||
|
await userStore.setBaseUdfDir(baseUdfDir)
|
||||||
|
|
||||||
const timezone = userInfoRes.timeZone ? userInfoRes.timeZone : 'UTC'
|
const timezone = userInfoRes.timeZone ? userInfoRes.timeZone : 'UTC'
|
||||||
await timezoneStore.setTimezone(timezone)
|
await timezoneStore.setTimezone(timezone)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ export function useUpdate(state: any) {
|
||||||
await userStore.setSessionId('')
|
await userStore.setSessionId('')
|
||||||
await userStore.setSecurityConfigType('')
|
await userStore.setSecurityConfigType('')
|
||||||
await userStore.setUserInfo({})
|
await userStore.setUserInfo({})
|
||||||
|
await userStore.setBaseResDir('')
|
||||||
|
await userStore.setBaseUdfDir('')
|
||||||
await router.push({ path: 'login' })
|
await router.push({ path: 'login' })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,9 @@ import ResourceUploadModal from './upload'
|
||||||
import ResourceRenameModal from './rename'
|
import ResourceRenameModal from './rename'
|
||||||
import styles from './index.module.scss'
|
import styles from './index.module.scss'
|
||||||
import type { Router } from 'vue-router'
|
import type { Router } from 'vue-router'
|
||||||
import Search from "@/components/input-search"
|
import Search from '@/components/input-search'
|
||||||
import { ResourceType } from "@/views/resource/components/resource/types";
|
import { ResourceType } from '@/views/resource/components/resource/types'
|
||||||
|
import { useUserStore } from '@/store/user/user'
|
||||||
|
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
|
|
@ -73,6 +74,7 @@ export default defineComponent({
|
||||||
handleCreateFile,
|
handleCreateFile,
|
||||||
} = useTable()
|
} = useTable()
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
variables.resourceType = props.resourceType
|
variables.resourceType = props.resourceType
|
||||||
|
|
||||||
|
|
@ -121,7 +123,8 @@ export default defineComponent({
|
||||||
|
|
||||||
const goBread = (fullName: string) => {
|
const goBread = (fullName: string) => {
|
||||||
const { resourceType, tenantCode } = variables
|
const { resourceType, tenantCode } = variables
|
||||||
if (fullName === '') {
|
const baseDir = resourceType === 'UDF' ? userStore.getBaseUdfDir : userStore.getBaseResDir
|
||||||
|
if (fullName === '' || !fullName.startsWith(baseDir)) {
|
||||||
router.push({ name: resourceType === 'UDF' ? 'resource-manage' : 'file-manage' })
|
router.push({ name: resourceType === 'UDF' ? 'resource-manage' : 'file-manage' })
|
||||||
} else {
|
} else {
|
||||||
router.push({
|
router.push({
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue