From 4bf097ee4022df05e730469f2f0984dad892c129 Mon Sep 17 00:00:00 2001 From: Aaron Wang Date: Mon, 17 Apr 2023 11:56:42 +0800 Subject: [PATCH] [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 --- .../api/controller/ResourcesController.java | 13 ++++++ .../api/service/ResourcesService.java | 9 +++++ .../service/impl/ResourcesServiceImpl.java | 40 ++++++++++++++++++- .../api/service/ResourcesServiceTest.java | 18 +++++++++ .../spi/enums/ResourceType.java | 3 +- .../plugin/storage/api/StorageOperate.java | 1 - .../storage/gcs/GcsStorageOperator.java | 2 + .../storage/hdfs/HdfsStorageOperator.java | 16 +++++--- .../storage/oss/OssStorageOperator.java | 2 + .../plugin/storage/s3/S3StorageOperator.java | 2 + .../content/components/user/use-dropdown.ts | 2 + .../src/service/modules/resources/index.ts | 10 +++++ dolphinscheduler-ui/src/service/service.ts | 2 + dolphinscheduler-ui/src/store/user/types.ts | 2 + dolphinscheduler-ui/src/store/user/user.ts | 14 +++++++ .../src/views/login/use-login.ts | 10 +++++ .../src/views/password/use-update.ts | 2 + .../resource/components/resource/index.tsx | 9 +++-- 18 files changed, 144 insertions(+), 13 deletions(-) diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ResourcesController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ResourcesController.java index 156e47605d..8945f59ea5 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ResourcesController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ResourcesController.java @@ -772,4 +772,17 @@ public class ResourcesController extends BaseController { 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 queryResourceBaseDir(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam(value = "type") ResourceType type) { + return resourceService.queryResourceBaseDir(loginUser, type); + } } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ResourcesService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ResourcesService.java index 82c1a4c01b..47b7d1bb92 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ResourcesService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ResourcesService.java @@ -271,4 +271,13 @@ public interface ResourcesService { Result queryResourceByFullName(User loginUser, String fullName, String tenantCode, ResourceType type) throws IOException; + /** + * get resource base dir + * + * @param loginUser login user + * @param type resource type + * @return + */ + Result queryResourceBaseDir(User loginUser, ResourceType type); + } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ResourcesServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ResourcesServiceImpl.java index 1175b8e6dd..6f83c4f914 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ResourcesServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ResourcesServiceImpl.java @@ -574,8 +574,10 @@ public class ResourcesServiceImpl extends BaseServiceImpl implements ResourcesSe } String tenantCode = getTenantCode(user); - - if (!isUserTenantValid(isAdmin(loginUser), tenantCode, resTenantCode)) { + String baseDir = isAdmin(loginUser) ? storageOperate.getDir(ResourceType.ALL, tenantCode) + : 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"); putMsg(result, Status.NO_CURRENT_OPERATING_PERMISSION); return result; @@ -1679,6 +1681,40 @@ public class ResourcesServiceImpl extends BaseServiceImpl implements ResourcesSe return result; } + /** + * get resource base dir + * + * @param loginUser login user + * @param type resource type + * @return + */ + @Override + public Result queryResourceBaseDir(User loginUser, ResourceType type) { + Result 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 * diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ResourcesServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ResourcesServiceTest.java index 925dec7f43..169775acae 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ResourcesServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ResourcesServiceTest.java @@ -892,6 +892,24 @@ public class ResourcesServiceTest { 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 result = resourcesService.queryResourceBaseDir(user, ResourceType.FILE); + Assertions.assertEquals(Status.SUCCESS.getMsg(), result.getMsg()); + } + private List getResourceList() { List resources = new ArrayList<>(); diff --git a/dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/enums/ResourceType.java b/dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/enums/ResourceType.java index a072f36ec4..16c49a1ecc 100644 --- a/dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/enums/ResourceType.java +++ b/dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/enums/ResourceType.java @@ -28,7 +28,8 @@ public enum ResourceType { * 0 file, 1 udf */ FILE(0, "file"), - UDF(1, "udf"); + UDF(1, "udf"), + ALL(2, "all"); ResourceType(int code, String descp) { this.code = code; diff --git a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-api/src/main/java/org/apache/dolphinscheduler/plugin/storage/api/StorageOperate.java b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-api/src/main/java/org/apache/dolphinscheduler/plugin/storage/api/StorageOperate.java index ef22ea4886..f000442d74 100644 --- a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-api/src/main/java/org/apache/dolphinscheduler/plugin/storage/api/StorageOperate.java +++ b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-api/src/main/java/org/apache/dolphinscheduler/plugin/storage/api/StorageOperate.java @@ -48,7 +48,6 @@ public interface StorageOperate { * @param tenantCode * @return */ - String getUdfDir(String tenantCode); /** diff --git a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-gcs/src/main/java/org/apache/dolphinscheduler/plugin/storage/gcs/GcsStorageOperator.java b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-gcs/src/main/java/org/apache/dolphinscheduler/plugin/storage/gcs/GcsStorageOperator.java index f02d15a176..4a2f386160 100644 --- a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-gcs/src/main/java/org/apache/dolphinscheduler/plugin/storage/gcs/GcsStorageOperator.java +++ b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-gcs/src/main/java/org/apache/dolphinscheduler/plugin/storage/gcs/GcsStorageOperator.java @@ -252,6 +252,8 @@ public class GcsStorageOperator implements Closeable, StorageOperate { return getUdfDir(tenantCode); case FILE: return getResDir(tenantCode); + case ALL: + return getGcsDataBasePath(); default: return EMPTY_STRING; } diff --git a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-hdfs/src/main/java/org/apache/dolphinscheduler/plugin/storage/hdfs/HdfsStorageOperator.java b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-hdfs/src/main/java/org/apache/dolphinscheduler/plugin/storage/hdfs/HdfsStorageOperator.java index a416cd07d6..d512d0571f 100644 --- a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-hdfs/src/main/java/org/apache/dolphinscheduler/plugin/storage/hdfs/HdfsStorageOperator.java +++ b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-hdfs/src/main/java/org/apache/dolphinscheduler/plugin/storage/hdfs/HdfsStorageOperator.java @@ -17,6 +17,7 @@ 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.FORMAT_S_S; 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 */ public static String getHdfsDir(ResourceType resourceType, String tenantCode) { - String hdfsDir = ""; - if (resourceType.equals(ResourceType.FILE)) { - hdfsDir = getHdfsResDir(tenantCode); - } else if (resourceType.equals(ResourceType.UDF)) { - hdfsDir = getHdfsUdfDir(tenantCode); + switch (resourceType) { + case UDF: + return getHdfsUdfDir(tenantCode); + case FILE: + return getHdfsResDir(tenantCode); + case ALL: + return getHdfsDataBasePath(); + default: + return EMPTY_STRING; } - return hdfsDir; } @Override diff --git a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-oss/src/main/java/org/apache/dolphinscheduler/plugin/storage/oss/OssStorageOperator.java b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-oss/src/main/java/org/apache/dolphinscheduler/plugin/storage/oss/OssStorageOperator.java index 523b021358..be4b158f63 100644 --- a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-oss/src/main/java/org/apache/dolphinscheduler/plugin/storage/oss/OssStorageOperator.java +++ b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-oss/src/main/java/org/apache/dolphinscheduler/plugin/storage/oss/OssStorageOperator.java @@ -268,6 +268,8 @@ public class OssStorageOperator implements Closeable, StorageOperate { return getUdfDir(tenantCode); case FILE: return getResDir(tenantCode); + case ALL: + return getOssDataBasePath(); default: return ""; } diff --git a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/main/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperator.java b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/main/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperator.java index ca54143c9b..ab95187e7b 100644 --- a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/main/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperator.java +++ b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/main/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperator.java @@ -290,6 +290,8 @@ public class S3StorageOperator implements Closeable, StorageOperate { return getUdfDir(tenantCode); case FILE: return getResDir(tenantCode); + case ALL: + return getS3DataBasePath(); default: return ""; } diff --git a/dolphinscheduler-ui/src/layouts/content/components/user/use-dropdown.ts b/dolphinscheduler-ui/src/layouts/content/components/user/use-dropdown.ts index 6ad6ea0517..2ef301f5de 100644 --- a/dolphinscheduler-ui/src/layouts/content/components/user/use-dropdown.ts +++ b/dolphinscheduler-ui/src/layouts/content/components/user/use-dropdown.ts @@ -41,6 +41,8 @@ export function useDropDown() { userStore.setSessionId('') userStore.setSecurityConfigType('') userStore.setUserInfo({}) + userStore.setBaseResDir('') + userStore.setBaseUdfDir('') cookies.remove('sessionId') router.push({ path: '/login' }) diff --git a/dolphinscheduler-ui/src/service/modules/resources/index.ts b/dolphinscheduler-ui/src/service/modules/resources/index.ts index 9a7fbe7b68..2081ad292e 100644 --- a/dolphinscheduler-ui/src/service/modules/resources/index.ts +++ b/dolphinscheduler-ui/src/service/modules/resources/index.ts @@ -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( params: ResourceTypeReq & FileNameReq & TenantCodeReq, ): any { diff --git a/dolphinscheduler-ui/src/service/service.ts b/dolphinscheduler-ui/src/service/service.ts index 97865a2ad4..fe02a94761 100644 --- a/dolphinscheduler-ui/src/service/service.ts +++ b/dolphinscheduler-ui/src/service/service.ts @@ -65,6 +65,8 @@ const err = (err: AxiosError): Promise => { userStore.setSessionId('') userStore.setSecurityConfigType('') userStore.setUserInfo({}) + userStore.setBaseResDir('') + userStore.setBaseUdfDir('') router.push({ path: '/login' }) } diff --git a/dolphinscheduler-ui/src/store/user/types.ts b/dolphinscheduler-ui/src/store/user/types.ts index 208d500f82..3b0b09da72 100644 --- a/dolphinscheduler-ui/src/store/user/types.ts +++ b/dolphinscheduler-ui/src/store/user/types.ts @@ -20,6 +20,8 @@ import type { UserInfoRes } from '@/service/modules/users/types' interface UserState { sessionId: string securityConfigType: string + baseResDir: string + baseUdfDir: string userInfo: UserInfoRes | {} } diff --git a/dolphinscheduler-ui/src/store/user/user.ts b/dolphinscheduler-ui/src/store/user/user.ts index 3f7e76644b..5405c2d687 100644 --- a/dolphinscheduler-ui/src/store/user/user.ts +++ b/dolphinscheduler-ui/src/store/user/user.ts @@ -24,6 +24,8 @@ export const useUserStore = defineStore({ state: (): UserState => ({ sessionId: '', securityConfigType: '', + baseResDir: '', + baseUdfDir: '', userInfo: {} }), persist: true, @@ -36,6 +38,12 @@ export const useUserStore = defineStore({ }, getUserInfo(): UserInfoRes | {} { return this.userInfo + }, + getBaseResDir(): string { + return this.baseResDir + }, + getBaseUdfDir(): string { + return this.baseUdfDir } }, actions: { @@ -47,6 +55,12 @@ export const useUserStore = defineStore({ }, setUserInfo(userInfo: UserInfoRes | {}): void { this.userInfo = userInfo + }, + setBaseResDir(baseResDir: string): void { + this.baseResDir = baseResDir + }, + setBaseUdfDir(baseUdfDir: string): void { + this.baseUdfDir = baseUdfDir } } }) diff --git a/dolphinscheduler-ui/src/views/login/use-login.ts b/dolphinscheduler-ui/src/views/login/use-login.ts index 6f62bd7486..1fd742c679 100644 --- a/dolphinscheduler-ui/src/views/login/use-login.ts +++ b/dolphinscheduler-ui/src/views/login/use-login.ts @@ -25,6 +25,7 @@ import type { UserInfoRes } from '@/service/modules/users/types' import { useRouteStore } from '@/store/route/route' import { useTimezoneStore } from '@/store/timezone/timezone' import cookies from 'js-cookie' +import {queryBaseDir} from "@/service/modules/resources"; export function useLogin(state: any) { const router: Router = useRouter() @@ -43,6 +44,15 @@ export function useLogin(state: any) { const userInfoRes: UserInfoRes = await getUserInfo() 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' await timezoneStore.setTimezone(timezone) diff --git a/dolphinscheduler-ui/src/views/password/use-update.ts b/dolphinscheduler-ui/src/views/password/use-update.ts index b8987298c9..896188f346 100644 --- a/dolphinscheduler-ui/src/views/password/use-update.ts +++ b/dolphinscheduler-ui/src/views/password/use-update.ts @@ -42,6 +42,8 @@ export function useUpdate(state: any) { await userStore.setSessionId('') await userStore.setSecurityConfigType('') await userStore.setUserInfo({}) + await userStore.setBaseResDir('') + await userStore.setBaseUdfDir('') await router.push({ path: 'login' }) } }) diff --git a/dolphinscheduler-ui/src/views/resource/components/resource/index.tsx b/dolphinscheduler-ui/src/views/resource/components/resource/index.tsx index 0f4f956cba..44e9d9f672 100644 --- a/dolphinscheduler-ui/src/views/resource/components/resource/index.tsx +++ b/dolphinscheduler-ui/src/views/resource/components/resource/index.tsx @@ -45,8 +45,9 @@ import ResourceUploadModal from './upload' import ResourceRenameModal from './rename' import styles from './index.module.scss' import type { Router } from 'vue-router' -import Search from "@/components/input-search" -import { ResourceType } from "@/views/resource/components/resource/types"; +import Search from '@/components/input-search' +import { ResourceType } from '@/views/resource/components/resource/types' +import { useUserStore } from '@/store/user/user' const props = { @@ -73,6 +74,7 @@ export default defineComponent({ handleCreateFile, } = useTable() + const userStore = useUserStore() variables.resourceType = props.resourceType @@ -121,7 +123,8 @@ export default defineComponent({ const goBread = (fullName: string) => { 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' }) } else { router.push({