Wenjun Ruan
5 months ago
committed by
GitHub
139 changed files with 6355 additions and 6832 deletions
@ -0,0 +1,34 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
import lombok.experimental.SuperBuilder; |
||||||
|
|
||||||
|
@Data |
||||||
|
@SuperBuilder |
||||||
|
public abstract class AbstractResourceCreateRequest { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
private String parentAbsoluteDirectory; |
||||||
|
private ResourceType type; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
import lombok.experimental.SuperBuilder; |
||||||
|
|
||||||
|
@Data |
||||||
|
@SuperBuilder |
||||||
|
public abstract class AbstractResourceDto { |
||||||
|
|
||||||
|
private String resourceAbsolutePath; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class CreateDirectoryDto { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String directoryAbsolutePath; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class CreateDirectoryRequest { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private ResourceType type; |
||||||
|
|
||||||
|
private String parentAbsoluteDirectory; |
||||||
|
|
||||||
|
private String directoryName; |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class CreateFileDto { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String fileAbsolutePath; |
||||||
|
|
||||||
|
private MultipartFile file; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class CreateFileFromContentDto { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String fileAbsolutePath; |
||||||
|
|
||||||
|
private String fileContent; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class CreateFileFromContentRequest { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
private ResourceType type; |
||||||
|
private String parentAbsoluteDirectory; |
||||||
|
private String fileName; |
||||||
|
private String fileContent; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class CreateFileRequest { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
private ResourceType type; |
||||||
|
private String parentAbsoluteDirectory; |
||||||
|
private String fileName; |
||||||
|
private MultipartFile file; |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class DeleteResourceDto { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
private String resourceAbsolutePath; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class DeleteResourceRequest { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
private String resourceAbsolutePath; |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class DownloadFileDto { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String fileAbsolutePath; |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class DownloadFileRequest { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String fileAbsolutePath; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class FetchFileContentDto { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
private String resourceFileAbsolutePath; |
||||||
|
private int skipLineNum; |
||||||
|
private int limit; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class FetchFileContentRequest { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
private String resourceFileAbsolutePath; |
||||||
|
private int skipLineNum; |
||||||
|
private int limit; |
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.enums.Status; |
||||||
|
import org.apache.dolphinscheduler.api.exceptions.ServiceException; |
||||||
|
import org.apache.dolphinscheduler.common.constants.Constants; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class PagingResourceItemRequest { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String resourceAbsolutePath; |
||||||
|
|
||||||
|
private ResourceType resourceType; |
||||||
|
|
||||||
|
private String resourceNameKeyWord; |
||||||
|
|
||||||
|
Integer pageNo; |
||||||
|
|
||||||
|
Integer pageSize; |
||||||
|
|
||||||
|
public void checkPageNoAndPageSize() { |
||||||
|
if (pageNo <= 0) { |
||||||
|
throw new ServiceException(Status.REQUEST_PARAMS_NOT_VALID_ERROR, Constants.PAGE_NUMBER); |
||||||
|
} |
||||||
|
if (pageSize <= 0) { |
||||||
|
throw new ServiceException(Status.REQUEST_PARAMS_NOT_VALID_ERROR, Constants.PAGE_SIZE); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class QueryResourceDto { |
||||||
|
|
||||||
|
private List<String> resourceAbsolutePaths; |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class RenameDirectoryDto { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String originDirectoryAbsolutePath; |
||||||
|
|
||||||
|
private String targetDirectoryAbsolutePath; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class RenameDirectoryRequest { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String directoryAbsolutePath; |
||||||
|
|
||||||
|
private String newDirectoryName; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class RenameFileDto { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String originFileAbsolutePath; |
||||||
|
|
||||||
|
private String targetFileAbsolutePath; |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class RenameFileRequest { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String fileAbsolutePath; |
||||||
|
|
||||||
|
private String newFileName; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class UpdateFileDto { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String fileAbsolutePath; |
||||||
|
|
||||||
|
private MultipartFile file; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class UpdateFileFromContentDto { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String fileAbsolutePath; |
||||||
|
|
||||||
|
private String fileContent; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class UpdateFileFromContentRequest { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String fileAbsolutePath; |
||||||
|
|
||||||
|
private String fileContent; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.dto.resources; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class UpdateFileRequest { |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
private String fileAbsolutePath; |
||||||
|
|
||||||
|
private MultipartFile file; |
||||||
|
|
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,24 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator; |
||||||
|
|
||||||
|
public interface ITransformer<T, R> { |
||||||
|
|
||||||
|
R transform(T t); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator; |
||||||
|
|
||||||
|
public interface IValidator<T> { |
||||||
|
|
||||||
|
void validate(T t); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.enums.Status; |
||||||
|
import org.apache.dolphinscheduler.api.exceptions.ServiceException; |
||||||
|
import org.apache.dolphinscheduler.api.validator.ITransformer; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
|
||||||
|
@AllArgsConstructor |
||||||
|
public abstract class AbstractResourceTransformer<T, R> implements ITransformer<T, R> { |
||||||
|
|
||||||
|
protected TenantDao tenantDao; |
||||||
|
|
||||||
|
protected StorageOperator storageOperator; |
||||||
|
|
||||||
|
protected String getParentDirectoryAbsolutePath(User loginUser, String parentAbsoluteDirectory, ResourceType type) { |
||||||
|
String tenantCode = tenantDao.queryOptionalById(loginUser.getTenantId()) |
||||||
|
.orElseThrow(() -> new ServiceException(Status.CURRENT_LOGIN_USER_TENANT_NOT_EXIST)) |
||||||
|
.getTenantCode(); |
||||||
|
String userResRootPath = storageOperator.getStorageBaseDirectory(tenantCode, type); |
||||||
|
// If the parent directory is / then will transform to userResRootPath
|
||||||
|
// This only happens when the front-end go into the resource page first
|
||||||
|
// todo: we need to change the front-end logic to avoid this
|
||||||
|
if (parentAbsoluteDirectory.equals("/")) { |
||||||
|
return userResRootPath; |
||||||
|
} |
||||||
|
|
||||||
|
if (!StringUtils.startsWith(parentAbsoluteDirectory, userResRootPath)) { |
||||||
|
throw new ServiceException(Status.ILLEGAL_RESOURCE_PATH, parentAbsoluteDirectory); |
||||||
|
} |
||||||
|
return parentAbsoluteDirectory; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,138 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.AbstractResourceDto; |
||||||
|
import org.apache.dolphinscheduler.api.enums.Status; |
||||||
|
import org.apache.dolphinscheduler.api.exceptions.ServiceException; |
||||||
|
import org.apache.dolphinscheduler.api.validator.IValidator; |
||||||
|
import org.apache.dolphinscheduler.common.enums.UserType; |
||||||
|
import org.apache.dolphinscheduler.common.utils.FileUtils; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.Tenant; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.ResourceMetadata; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
|
||||||
|
import com.google.common.io.Files; |
||||||
|
|
||||||
|
public abstract class AbstractResourceValidator<T> implements IValidator<T> { |
||||||
|
|
||||||
|
private static final Set<String> FILE_SUFFIXES_WHICH_CAN_FETCH_CONTENT = new HashSet<>(Arrays.asList( |
||||||
|
StringUtils.defaultIfBlank(FileUtils.getResourceViewSuffixes(), "").split(","))); |
||||||
|
|
||||||
|
protected final StorageOperator storageOperator; |
||||||
|
|
||||||
|
private final TenantDao tenantDao; |
||||||
|
|
||||||
|
public AbstractResourceValidator(StorageOperator storageOperator, TenantDao tenantDao) { |
||||||
|
this.storageOperator = storageOperator; |
||||||
|
this.tenantDao = tenantDao; |
||||||
|
} |
||||||
|
|
||||||
|
public void exceptionResourceAbsolutePathInvalidated(String resourceAbsolutePath) { |
||||||
|
if (StringUtils.isBlank(resourceAbsolutePath)) { |
||||||
|
throw new ServiceException("The resource path is null"); |
||||||
|
} |
||||||
|
if (!resourceAbsolutePath.startsWith(storageOperator.getStorageBaseDirectory())) { |
||||||
|
throw new ServiceException("Invalidated resource path: " + resourceAbsolutePath); |
||||||
|
} |
||||||
|
if (resourceAbsolutePath.contains("..")) { |
||||||
|
throw new ServiceException("Invalidated resource path: " + resourceAbsolutePath); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void exceptionFileInvalidated(MultipartFile file) { |
||||||
|
if (file == null) { |
||||||
|
throw new ServiceException("The file is null"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void exceptionFileContentInvalidated(String fileContent) { |
||||||
|
if (StringUtils.isEmpty(fileContent)) { |
||||||
|
throw new ServiceException("The file content is null"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void exceptionFileContentCannotFetch(String fileAbsolutePath) { |
||||||
|
String fileExtension = Files.getFileExtension(fileAbsolutePath); |
||||||
|
if (!FILE_SUFFIXES_WHICH_CAN_FETCH_CONTENT.contains(fileExtension)) { |
||||||
|
throw new ServiceException("The file type: " + fileExtension + " cannot be fetched"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void exceptionResourceNotExists(String resourceAbsolutePath) { |
||||||
|
if (!storageOperator.exists(resourceAbsolutePath)) { |
||||||
|
throw new ServiceException("Thr resource is not exists: " + resourceAbsolutePath); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void exceptionResourceExists(String resourceAbsolutePath) { |
||||||
|
if (storageOperator.exists(resourceAbsolutePath)) { |
||||||
|
throw new ServiceException("The resource is already exist: " + resourceAbsolutePath); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void exceptionResourceIsNotDirectory(String resourceAbsolutePath) { |
||||||
|
if (StringUtils.isNotEmpty(Files.getFileExtension(resourceAbsolutePath))) { |
||||||
|
throw new ServiceException("The path is not a directory: " + resourceAbsolutePath); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void exceptionResourceIsNotFile(String fileAbsolutePath) { |
||||||
|
if (StringUtils.isEmpty(Files.getFileExtension(fileAbsolutePath))) { |
||||||
|
throw new ServiceException("The path is not a file: " + fileAbsolutePath); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void exceptionUserNoResourcePermission(User user, AbstractResourceDto resourceDto) { |
||||||
|
exceptionUserNoResourcePermission(user, resourceDto.getResourceAbsolutePath()); |
||||||
|
} |
||||||
|
|
||||||
|
public void exceptionUserNoResourcePermission(User user, String resourceAbsolutePath) { |
||||||
|
if (user.getUserType() == UserType.ADMIN_USER) { |
||||||
|
return; |
||||||
|
} |
||||||
|
// check if the user have resource tenant permission
|
||||||
|
// Parse the resource path to get the tenant code
|
||||||
|
ResourceMetadata resourceMetaData = storageOperator.getResourceMetaData(resourceAbsolutePath); |
||||||
|
|
||||||
|
if (!resourceAbsolutePath.startsWith(resourceMetaData.getResourceBaseDirectory())) { |
||||||
|
throw new ServiceException("Invalidated resource path: " + resourceAbsolutePath); |
||||||
|
} |
||||||
|
|
||||||
|
// todo: inject the tenant when login
|
||||||
|
Tenant tenant = tenantDao.queryOptionalById(user.getTenantId()) |
||||||
|
.orElseThrow(() -> new ServiceException(Status.TENANT_NOT_EXIST, user.getTenantId())); |
||||||
|
String userTenant = tenant.getTenantCode(); |
||||||
|
if (!userTenant.equals(resourceMetaData.getTenant())) { |
||||||
|
throw new ServiceException( |
||||||
|
"The user's tenant is " + userTenant + " have no permission to access the resource: " |
||||||
|
+ resourceAbsolutePath); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.CreateDirectoryDto; |
||||||
|
import org.apache.dolphinscheduler.api.exceptions.ServiceException; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
import com.google.common.io.Files; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class CreateDirectoryDtoValidator extends AbstractResourceValidator<CreateDirectoryDto> { |
||||||
|
|
||||||
|
public CreateDirectoryDtoValidator(StorageOperator storageOperator, TenantDao tenantDao) { |
||||||
|
super(storageOperator, tenantDao); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void validate(CreateDirectoryDto createDirectoryDto) { |
||||||
|
String directoryAbsolutePath = createDirectoryDto.getDirectoryAbsolutePath(); |
||||||
|
|
||||||
|
exceptionResourceAbsolutePathInvalidated(directoryAbsolutePath); |
||||||
|
exceptionResourceExists(directoryAbsolutePath); |
||||||
|
exceptionUserNoResourcePermission(createDirectoryDto.getLoginUser(), directoryAbsolutePath); |
||||||
|
exceptionResourceIsNotDirectory(directoryAbsolutePath); |
||||||
|
if (StringUtils.isNotEmpty(Files.getFileExtension(directoryAbsolutePath))) { |
||||||
|
throw new ServiceException("The path is not a directory: " + directoryAbsolutePath); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,87 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.CreateDirectoryDto; |
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.CreateDirectoryRequest; |
||||||
|
import org.apache.dolphinscheduler.api.enums.Status; |
||||||
|
import org.apache.dolphinscheduler.api.exceptions.ServiceException; |
||||||
|
import org.apache.dolphinscheduler.api.validator.ITransformer; |
||||||
|
import org.apache.dolphinscheduler.common.utils.FileUtils; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class CreateDirectoryRequestTransformer implements ITransformer<CreateDirectoryRequest, CreateDirectoryDto> { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private TenantDao tenantDao; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private StorageOperator storageOperator; |
||||||
|
|
||||||
|
@Override |
||||||
|
public CreateDirectoryDto transform(CreateDirectoryRequest createDirectoryRequest) { |
||||||
|
validateCreateDirectoryRequest(createDirectoryRequest); |
||||||
|
return doTransform(createDirectoryRequest); |
||||||
|
} |
||||||
|
|
||||||
|
private CreateDirectoryDto doTransform(CreateDirectoryRequest createDirectoryRequest) { |
||||||
|
String directoryAbsolutePath = getDirectoryAbsolutePath(createDirectoryRequest); |
||||||
|
return CreateDirectoryDto.builder() |
||||||
|
.loginUser(createDirectoryRequest.getLoginUser()) |
||||||
|
.directoryAbsolutePath(directoryAbsolutePath) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
|
||||||
|
private void validateCreateDirectoryRequest(CreateDirectoryRequest createDirectoryRequest) { |
||||||
|
checkNotNull(createDirectoryRequest.getLoginUser(), "loginUser is null"); |
||||||
|
checkNotNull(createDirectoryRequest.getType(), "resource type is null"); |
||||||
|
checkNotNull(createDirectoryRequest.getDirectoryName(), "directory name is null"); |
||||||
|
checkNotNull(createDirectoryRequest.getParentAbsoluteDirectory(), "parent directory is null"); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private String getDirectoryAbsolutePath(CreateDirectoryRequest createDirectoryRequest) { |
||||||
|
String tenantCode = tenantDao.queryOptionalById(createDirectoryRequest.getLoginUser().getTenantId()) |
||||||
|
.orElseThrow(() -> new ServiceException(Status.CURRENT_LOGIN_USER_TENANT_NOT_EXIST)) |
||||||
|
.getTenantCode(); |
||||||
|
String userResRootPath = storageOperator.getStorageBaseDirectory(tenantCode, createDirectoryRequest.getType()); |
||||||
|
String parentDirectoryName = createDirectoryRequest.getParentAbsoluteDirectory(); |
||||||
|
String directoryName = createDirectoryRequest.getDirectoryName(); |
||||||
|
|
||||||
|
// If the parent directory is / then will transform to userResRootPath
|
||||||
|
// This only happens when the front-end go into the resource page first
|
||||||
|
// todo: we need to change the front-end logic to avoid this
|
||||||
|
if (parentDirectoryName.equals("/")) { |
||||||
|
return FileUtils.concatFilePath(userResRootPath, directoryName); |
||||||
|
} |
||||||
|
|
||||||
|
if (!StringUtils.startsWith(parentDirectoryName, userResRootPath)) { |
||||||
|
throw new ServiceException(Status.ILLEGAL_RESOURCE_PATH, parentDirectoryName); |
||||||
|
} |
||||||
|
return FileUtils.concatFilePath(parentDirectoryName, directoryName); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.CreateFileDto; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class CreateFileDtoValidator extends AbstractResourceValidator<CreateFileDto> { |
||||||
|
|
||||||
|
public CreateFileDtoValidator(StorageOperator storageOperator, TenantDao tenantDao) { |
||||||
|
super(storageOperator, tenantDao); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void validate(CreateFileDto createFileDto) { |
||||||
|
String fileAbsolutePath = createFileDto.getFileAbsolutePath(); |
||||||
|
User loginUser = createFileDto.getLoginUser(); |
||||||
|
MultipartFile file = createFileDto.getFile(); |
||||||
|
|
||||||
|
exceptionResourceAbsolutePathInvalidated(fileAbsolutePath); |
||||||
|
exceptionResourceExists(fileAbsolutePath); |
||||||
|
exceptionFileInvalidated(file); |
||||||
|
exceptionUserNoResourcePermission(loginUser, fileAbsolutePath); |
||||||
|
exceptionResourceIsNotFile(fileAbsolutePath); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.CreateFileFromContentDto; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class CreateFileFromContentDtoValidator extends AbstractResourceValidator<CreateFileFromContentDto> { |
||||||
|
|
||||||
|
public CreateFileFromContentDtoValidator(StorageOperator storageOperator, TenantDao tenantDao) { |
||||||
|
super(storageOperator, tenantDao); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void validate(CreateFileFromContentDto createFileFromContentDto) { |
||||||
|
String fileAbsolutePath = createFileFromContentDto.getFileAbsolutePath(); |
||||||
|
User loginUser = createFileFromContentDto.getLoginUser(); |
||||||
|
String fileContent = createFileFromContentDto.getFileContent(); |
||||||
|
|
||||||
|
exceptionResourceAbsolutePathInvalidated(fileAbsolutePath); |
||||||
|
exceptionResourceIsNotFile(fileAbsolutePath); |
||||||
|
exceptionResourceExists(fileAbsolutePath); |
||||||
|
exceptionUserNoResourcePermission(loginUser, fileAbsolutePath); |
||||||
|
exceptionFileContentInvalidated(fileContent); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.DeleteResourceDto; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class DeleteResourceDtoValidator extends AbstractResourceValidator<DeleteResourceDto> { |
||||||
|
|
||||||
|
public DeleteResourceDtoValidator(StorageOperator storageOperator, TenantDao tenantDao) { |
||||||
|
super(storageOperator, tenantDao); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void validate(DeleteResourceDto deleteResourceDto) { |
||||||
|
String resourceAbsolutePath = deleteResourceDto.getResourceAbsolutePath(); |
||||||
|
User loginUser = deleteResourceDto.getLoginUser(); |
||||||
|
|
||||||
|
exceptionResourceAbsolutePathInvalidated(resourceAbsolutePath); |
||||||
|
exceptionResourceNotExists(resourceAbsolutePath); |
||||||
|
exceptionUserNoResourcePermission(loginUser, resourceAbsolutePath); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.DownloadFileDto; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class DownloadFileDtoValidator extends AbstractResourceValidator<DownloadFileDto> { |
||||||
|
|
||||||
|
public DownloadFileDtoValidator(StorageOperator storageOperator, TenantDao tenantDao) { |
||||||
|
super(storageOperator, tenantDao); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void validate(DownloadFileDto downloadFileDto) { |
||||||
|
String fileAbsolutePath = downloadFileDto.getFileAbsolutePath(); |
||||||
|
User loginUser = downloadFileDto.getLoginUser(); |
||||||
|
|
||||||
|
exceptionResourceNotExists(fileAbsolutePath); |
||||||
|
exceptionResourceAbsolutePathInvalidated(fileAbsolutePath); |
||||||
|
exceptionResourceIsNotFile(fileAbsolutePath); |
||||||
|
exceptionUserNoResourcePermission(loginUser, fileAbsolutePath); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.FetchFileContentDto; |
||||||
|
import org.apache.dolphinscheduler.api.exceptions.ServiceException; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class FetchFileContentDtoValidator extends AbstractResourceValidator<FetchFileContentDto> { |
||||||
|
|
||||||
|
public FetchFileContentDtoValidator(StorageOperator storageOperator, TenantDao tenantDao) { |
||||||
|
super(storageOperator, tenantDao); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void validate(FetchFileContentDto fetchFileContentDto) { |
||||||
|
if (fetchFileContentDto.getSkipLineNum() < 0) { |
||||||
|
throw new ServiceException("skipLineNum must be greater than or equal to 0"); |
||||||
|
} |
||||||
|
String resourceFileAbsolutePath = fetchFileContentDto.getResourceFileAbsolutePath(); |
||||||
|
User loginUser = fetchFileContentDto.getLoginUser(); |
||||||
|
|
||||||
|
exceptionResourceAbsolutePathInvalidated(resourceFileAbsolutePath); |
||||||
|
exceptionResourceIsNotFile(resourceFileAbsolutePath); |
||||||
|
exceptionUserNoResourcePermission(loginUser, resourceFileAbsolutePath); |
||||||
|
exceptionFileContentCannotFetch(resourceFileAbsolutePath); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,71 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.CreateFileFromContentDto; |
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.CreateFileFromContentRequest; |
||||||
|
import org.apache.dolphinscheduler.common.utils.FileUtils; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class FileFromContentRequestTransformer |
||||||
|
extends |
||||||
|
AbstractResourceTransformer<CreateFileFromContentRequest, CreateFileFromContentDto> { |
||||||
|
|
||||||
|
public FileFromContentRequestTransformer(TenantDao tenantDao, StorageOperator storageOperator) { |
||||||
|
super(tenantDao, storageOperator); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public CreateFileFromContentDto transform(CreateFileFromContentRequest createFileFromContentRequest) { |
||||||
|
validateCreateFileRequest(createFileFromContentRequest); |
||||||
|
return doTransform(createFileFromContentRequest); |
||||||
|
} |
||||||
|
|
||||||
|
private void validateCreateFileRequest(CreateFileFromContentRequest createFileFromContentRequest) { |
||||||
|
checkNotNull(createFileFromContentRequest.getLoginUser(), "loginUser is null"); |
||||||
|
checkNotNull(createFileFromContentRequest.getType(), "resource type is null"); |
||||||
|
checkNotNull(createFileFromContentRequest.getFileName(), "file name is null"); |
||||||
|
checkNotNull(createFileFromContentRequest.getParentAbsoluteDirectory(), "parent directory is null"); |
||||||
|
checkNotNull(createFileFromContentRequest.getFileContent(), "file content is null"); |
||||||
|
} |
||||||
|
|
||||||
|
private CreateFileFromContentDto doTransform(CreateFileFromContentRequest createFileFromContentRequest) { |
||||||
|
String fileAbsolutePath = getFileAbsolutePath(createFileFromContentRequest); |
||||||
|
return CreateFileFromContentDto.builder() |
||||||
|
.loginUser(createFileFromContentRequest.getLoginUser()) |
||||||
|
.fileAbsolutePath(fileAbsolutePath) |
||||||
|
.fileContent(createFileFromContentRequest.getFileContent()) |
||||||
|
.build(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private String getFileAbsolutePath(CreateFileFromContentRequest createFileFromContentRequest) { |
||||||
|
String parentDirectoryAbsolutePath = getParentDirectoryAbsolutePath( |
||||||
|
createFileFromContentRequest.getLoginUser(), |
||||||
|
createFileFromContentRequest.getParentAbsoluteDirectory(), |
||||||
|
createFileFromContentRequest.getType()); |
||||||
|
return FileUtils.concatFilePath(parentDirectoryAbsolutePath, createFileFromContentRequest.getFileName()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,68 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.CreateFileDto; |
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.CreateFileRequest; |
||||||
|
import org.apache.dolphinscheduler.common.utils.FileUtils; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class FileRequestTransformer extends AbstractResourceTransformer<CreateFileRequest, CreateFileDto> { |
||||||
|
|
||||||
|
public FileRequestTransformer(TenantDao tenantDao, StorageOperator storageOperator) { |
||||||
|
super(tenantDao, storageOperator); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public CreateFileDto transform(CreateFileRequest createFileRequest) { |
||||||
|
validateCreateFileRequest(createFileRequest); |
||||||
|
return doTransform(createFileRequest); |
||||||
|
} |
||||||
|
|
||||||
|
private void validateCreateFileRequest(CreateFileRequest createFileRequest) { |
||||||
|
checkNotNull(createFileRequest.getLoginUser(), "loginUser is null"); |
||||||
|
checkNotNull(createFileRequest.getType(), "resource type is null"); |
||||||
|
checkNotNull(createFileRequest.getFileName(), "file name is null"); |
||||||
|
checkNotNull(createFileRequest.getParentAbsoluteDirectory(), "parent directory is null"); |
||||||
|
checkNotNull(createFileRequest.getFile(), "file is null"); |
||||||
|
} |
||||||
|
|
||||||
|
private CreateFileDto doTransform(CreateFileRequest createFileRequest) { |
||||||
|
String fileAbsolutePath = getFileAbsolutePath(createFileRequest); |
||||||
|
return CreateFileDto.builder() |
||||||
|
.loginUser(createFileRequest.getLoginUser()) |
||||||
|
.file(createFileRequest.getFile()) |
||||||
|
.fileAbsolutePath(fileAbsolutePath) |
||||||
|
.build(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private String getFileAbsolutePath(CreateFileRequest createFileRequest) { |
||||||
|
String parentDirectoryAbsolutePath = getParentDirectoryAbsolutePath( |
||||||
|
createFileRequest.getLoginUser(), |
||||||
|
createFileRequest.getParentAbsoluteDirectory(), |
||||||
|
createFileRequest.getType()); |
||||||
|
return FileUtils.concatFilePath(parentDirectoryAbsolutePath, createFileRequest.getFileName()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,90 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.PagingResourceItemRequest; |
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.QueryResourceDto; |
||||||
|
import org.apache.dolphinscheduler.api.validator.ITransformer; |
||||||
|
import org.apache.dolphinscheduler.common.enums.UserType; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.Tenant; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
import com.google.common.collect.Lists; |
||||||
|
|
||||||
|
@Component |
||||||
|
@AllArgsConstructor |
||||||
|
public class PagingResourceItemRequestTransformer implements ITransformer<PagingResourceItemRequest, QueryResourceDto> { |
||||||
|
|
||||||
|
private final StorageOperator storageOperator; |
||||||
|
|
||||||
|
private final TenantDao tenantDao; |
||||||
|
|
||||||
|
@Override |
||||||
|
public QueryResourceDto transform(PagingResourceItemRequest pagingResourceItemRequest) { |
||||||
|
validatePagingResourceItemRequest(pagingResourceItemRequest); |
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(pagingResourceItemRequest.getResourceAbsolutePath())) { |
||||||
|
// query from the given path
|
||||||
|
return QueryResourceDto.builder() |
||||||
|
.resourceAbsolutePaths(Lists.newArrayList(pagingResourceItemRequest.getResourceAbsolutePath())) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
|
||||||
|
ResourceType resourceType = pagingResourceItemRequest.getResourceType(); |
||||||
|
User loginUser = pagingResourceItemRequest.getLoginUser(); |
||||||
|
if (loginUser.getUserType() == UserType.ADMIN_USER) { |
||||||
|
// If the current user is admin
|
||||||
|
// then will query all tenant resources
|
||||||
|
List<String> resourceAbsolutePaths = tenantDao.queryAll() |
||||||
|
.stream() |
||||||
|
.map(tenant -> storageOperator.getStorageBaseDirectory(tenant.getTenantCode(), resourceType)) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
return QueryResourceDto.builder() |
||||||
|
.resourceAbsolutePaths(resourceAbsolutePaths) |
||||||
|
.build(); |
||||||
|
} else { |
||||||
|
// todo: inject the tenantCode when login
|
||||||
|
Tenant tenant = tenantDao.queryById(loginUser.getTenantId()); |
||||||
|
String storageBaseDirectory = storageOperator.getStorageBaseDirectory(tenant.getTenantCode(), resourceType); |
||||||
|
return QueryResourceDto.builder() |
||||||
|
.resourceAbsolutePaths(Lists.newArrayList(storageBaseDirectory)) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void validatePagingResourceItemRequest(PagingResourceItemRequest pagingResourceItemRequest) { |
||||||
|
checkNotNull(pagingResourceItemRequest.getLoginUser(), "loginUser is null"); |
||||||
|
checkNotNull(pagingResourceItemRequest.getResourceType(), "resourceType is null"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.RenameDirectoryDto; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class RenameDirectoryDtoValidator extends AbstractResourceValidator<RenameDirectoryDto> { |
||||||
|
|
||||||
|
public RenameDirectoryDtoValidator(StorageOperator storageOperator, TenantDao tenantDao) { |
||||||
|
super(storageOperator, tenantDao); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void validate(RenameDirectoryDto renameDirectoryDto) { |
||||||
|
String originDirectoryAbsolutePath = renameDirectoryDto.getOriginDirectoryAbsolutePath(); |
||||||
|
User loginUser = renameDirectoryDto.getLoginUser(); |
||||||
|
String targetDirectoryAbsolutePath = renameDirectoryDto.getTargetDirectoryAbsolutePath(); |
||||||
|
|
||||||
|
exceptionResourceAbsolutePathInvalidated(originDirectoryAbsolutePath); |
||||||
|
exceptionResourceIsNotDirectory(originDirectoryAbsolutePath); |
||||||
|
exceptionResourceNotExists(originDirectoryAbsolutePath); |
||||||
|
exceptionUserNoResourcePermission(loginUser, originDirectoryAbsolutePath); |
||||||
|
|
||||||
|
exceptionResourceAbsolutePathInvalidated(targetDirectoryAbsolutePath); |
||||||
|
exceptionResourceIsNotDirectory(targetDirectoryAbsolutePath); |
||||||
|
exceptionResourceExists(targetDirectoryAbsolutePath); |
||||||
|
exceptionUserNoResourcePermission(loginUser, targetDirectoryAbsolutePath); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.RenameDirectoryDto; |
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.RenameDirectoryRequest; |
||||||
|
import org.apache.dolphinscheduler.api.validator.ITransformer; |
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Component |
||||||
|
public class RenameDirectoryRequestTransformer implements ITransformer<RenameDirectoryRequest, RenameDirectoryDto> { |
||||||
|
|
||||||
|
@Override |
||||||
|
public RenameDirectoryDto transform(RenameDirectoryRequest renameDirectoryRequest) { |
||||||
|
String originDirectoryAbsolutePath = renameDirectoryRequest.getDirectoryAbsolutePath(); |
||||||
|
String targetDirectoryName = renameDirectoryRequest.getNewDirectoryName(); |
||||||
|
|
||||||
|
String targetDirectoryAbsolutePath = |
||||||
|
getTargetDirectoryAbsolutePath(originDirectoryAbsolutePath, targetDirectoryName); |
||||||
|
|
||||||
|
return RenameDirectoryDto.builder() |
||||||
|
.loginUser(renameDirectoryRequest.getLoginUser()) |
||||||
|
.originDirectoryAbsolutePath(originDirectoryAbsolutePath) |
||||||
|
.targetDirectoryAbsolutePath(targetDirectoryAbsolutePath) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
|
||||||
|
private String getTargetDirectoryAbsolutePath(String originDirectoryAbsolutePath, String targetDirectoryName) { |
||||||
|
String originDirectoryParentAbsolutePath = StringUtils.substringBeforeLast( |
||||||
|
originDirectoryAbsolutePath, File.separator); |
||||||
|
return originDirectoryParentAbsolutePath + File.separator + targetDirectoryName; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.RenameFileDto; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class RenameFileDtoValidator extends AbstractResourceValidator<RenameFileDto> { |
||||||
|
|
||||||
|
public RenameFileDtoValidator(StorageOperator storageOperator, TenantDao tenantDao) { |
||||||
|
super(storageOperator, tenantDao); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void validate(RenameFileDto renameFileDto) { |
||||||
|
String originFileAbsolutePath = renameFileDto.getOriginFileAbsolutePath(); |
||||||
|
User loginUser = renameFileDto.getLoginUser(); |
||||||
|
String targetFileAbsolutePath = renameFileDto.getTargetFileAbsolutePath(); |
||||||
|
|
||||||
|
exceptionResourceAbsolutePathInvalidated(originFileAbsolutePath); |
||||||
|
exceptionResourceNotExists(originFileAbsolutePath); |
||||||
|
exceptionResourceIsNotFile(originFileAbsolutePath); |
||||||
|
exceptionUserNoResourcePermission(loginUser, originFileAbsolutePath); |
||||||
|
|
||||||
|
exceptionResourceAbsolutePathInvalidated(targetFileAbsolutePath); |
||||||
|
exceptionResourceExists(targetFileAbsolutePath); |
||||||
|
exceptionResourceIsNotFile(targetFileAbsolutePath); |
||||||
|
exceptionUserNoResourcePermission(loginUser, targetFileAbsolutePath); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.RenameFileDto; |
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.RenameFileRequest; |
||||||
|
import org.apache.dolphinscheduler.api.validator.ITransformer; |
||||||
|
import org.apache.dolphinscheduler.common.utils.FileUtils; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.ResourceMetadata; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class RenameFileRequestTransformer implements ITransformer<RenameFileRequest, RenameFileDto> { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private StorageOperator storageOperator; |
||||||
|
|
||||||
|
@Override |
||||||
|
public RenameFileDto transform(RenameFileRequest renameFileRequest) { |
||||||
|
ResourceMetadata resourceMetaData = |
||||||
|
storageOperator.getResourceMetaData(renameFileRequest.getFileAbsolutePath()); |
||||||
|
return RenameFileDto.builder() |
||||||
|
.loginUser(renameFileRequest.getLoginUser()) |
||||||
|
.originFileAbsolutePath(renameFileRequest.getFileAbsolutePath()) |
||||||
|
.targetFileAbsolutePath(FileUtils.concatFilePath(resourceMetaData.getResourceParentAbsolutePath(), |
||||||
|
renameFileRequest.getNewFileName())) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.UpdateFileDto; |
||||||
|
import org.apache.dolphinscheduler.api.exceptions.ServiceException; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
|
||||||
|
import com.google.common.io.Files; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class UpdateFileDtoValidator extends AbstractResourceValidator<UpdateFileDto> { |
||||||
|
|
||||||
|
public UpdateFileDtoValidator(StorageOperator storageOperator, TenantDao tenantDao) { |
||||||
|
super(storageOperator, tenantDao); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void validate(UpdateFileDto updateFileDto) { |
||||||
|
String fileAbsolutePath = updateFileDto.getFileAbsolutePath(); |
||||||
|
User loginUser = updateFileDto.getLoginUser(); |
||||||
|
MultipartFile file = updateFileDto.getFile(); |
||||||
|
|
||||||
|
if (!Objects.equals(Files.getFileExtension(file.getName()), |
||||||
|
Files.getFileExtension(updateFileDto.getFileAbsolutePath()))) { |
||||||
|
throw new ServiceException("file extension cannot not change"); |
||||||
|
} |
||||||
|
|
||||||
|
exceptionResourceAbsolutePathInvalidated(fileAbsolutePath); |
||||||
|
exceptionResourceNotExists(fileAbsolutePath); |
||||||
|
exceptionResourceIsNotFile(fileAbsolutePath); |
||||||
|
exceptionUserNoResourcePermission(loginUser, fileAbsolutePath); |
||||||
|
exceptionFileInvalidated(file); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.UpdateFileFromContentDto; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class UpdateFileFromContentDtoValidator extends AbstractResourceValidator<UpdateFileFromContentDto> { |
||||||
|
|
||||||
|
public UpdateFileFromContentDtoValidator(StorageOperator storageOperator, TenantDao tenantDao) { |
||||||
|
super(storageOperator, tenantDao); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void validate(UpdateFileFromContentDto updateFileFromContentDto) { |
||||||
|
String fileAbsolutePath = updateFileFromContentDto.getFileAbsolutePath(); |
||||||
|
User loginUser = updateFileFromContentDto.getLoginUser(); |
||||||
|
String fileContent = updateFileFromContentDto.getFileContent(); |
||||||
|
|
||||||
|
exceptionResourceAbsolutePathInvalidated(fileAbsolutePath); |
||||||
|
exceptionResourceNotExists(fileAbsolutePath); |
||||||
|
exceptionResourceIsNotFile(fileAbsolutePath); |
||||||
|
exceptionUserNoResourcePermission(loginUser, fileAbsolutePath); |
||||||
|
exceptionFileContentCannotFetch(fileAbsolutePath); |
||||||
|
exceptionFileContentInvalidated(fileContent); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.UpdateFileFromContentDto; |
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.UpdateFileFromContentRequest; |
||||||
|
import org.apache.dolphinscheduler.api.validator.ITransformer; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class UpdateFileFromContentRequestTransformer |
||||||
|
implements |
||||||
|
ITransformer<UpdateFileFromContentRequest, UpdateFileFromContentDto> { |
||||||
|
|
||||||
|
@Override |
||||||
|
public UpdateFileFromContentDto transform(UpdateFileFromContentRequest updateFileContentRequest) { |
||||||
|
return UpdateFileFromContentDto.builder() |
||||||
|
.loginUser(updateFileContentRequest.getLoginUser()) |
||||||
|
.fileAbsolutePath(updateFileContentRequest.getFileAbsolutePath()) |
||||||
|
.fileContent(updateFileContentRequest.getFileContent()) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.UpdateFileDto; |
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.UpdateFileRequest; |
||||||
|
import org.apache.dolphinscheduler.api.validator.ITransformer; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class UpdateFileRequestTransformer implements ITransformer<UpdateFileRequest, UpdateFileDto> { |
||||||
|
|
||||||
|
@Override |
||||||
|
public UpdateFileDto transform(UpdateFileRequest updateFileRequest) { |
||||||
|
return UpdateFileDto.builder() |
||||||
|
.loginUser(updateFileRequest.getLoginUser()) |
||||||
|
.fileAbsolutePath(updateFileRequest.getFileAbsolutePath()) |
||||||
|
.file(updateFileRequest.getFile()) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,74 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.vo; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageEntity; |
||||||
|
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.util.Date; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class ResourceItemVO { |
||||||
|
|
||||||
|
// todo: remove this field, directly use fileName
|
||||||
|
private String alias; |
||||||
|
|
||||||
|
// todo: use tenantName instead of userName
|
||||||
|
private String userName; |
||||||
|
|
||||||
|
private String fileName; |
||||||
|
|
||||||
|
private String fullName; |
||||||
|
|
||||||
|
private boolean isDirectory; |
||||||
|
|
||||||
|
private ResourceType type; |
||||||
|
|
||||||
|
private long size; |
||||||
|
|
||||||
|
private Date createTime; |
||||||
|
|
||||||
|
private Date updateTime; |
||||||
|
|
||||||
|
public ResourceItemVO(StorageEntity storageEntity) { |
||||||
|
this.isDirectory = storageEntity.isDirectory(); |
||||||
|
this.alias = storageEntity.getFileName(); |
||||||
|
this.fileName = storageEntity.getFileName(); |
||||||
|
this.fullName = storageEntity.getFullName(); |
||||||
|
this.type = storageEntity.getType(); |
||||||
|
this.size = storageEntity.getSize(); |
||||||
|
this.createTime = storageEntity.getCreateTime(); |
||||||
|
this.updateTime = storageEntity.getUpdateTime(); |
||||||
|
|
||||||
|
if (isDirectory) { |
||||||
|
alias = StringUtils.removeEndIgnoreCase(alias, File.separator); |
||||||
|
fileName = StringUtils.removeEndIgnoreCase(fileName, File.separator); |
||||||
|
fullName = StringUtils.removeEndIgnoreCase(fullName, File.separator); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.vo.resources; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class FetchFileContentResponse { |
||||||
|
|
||||||
|
private String content; |
||||||
|
|
||||||
|
} |
@ -1,657 +0,0 @@ |
|||||||
/* |
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
* contributor license agreements. See the NOTICE file distributed with |
|
||||||
* this work for additional information regarding copyright ownership. |
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
* (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.api.service; |
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals; |
|
||||||
import static org.mockito.ArgumentMatchers.eq; |
|
||||||
import static org.mockito.Mockito.when; |
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.api.dto.resources.DeleteDataTransferResponse; |
|
||||||
import org.apache.dolphinscheduler.api.dto.resources.ResourceComponent; |
|
||||||
import org.apache.dolphinscheduler.api.enums.Status; |
|
||||||
import org.apache.dolphinscheduler.api.exceptions.ServiceException; |
|
||||||
import org.apache.dolphinscheduler.api.permission.ResourcePermissionCheckService; |
|
||||||
import org.apache.dolphinscheduler.api.service.impl.ResourcesServiceImpl; |
|
||||||
import org.apache.dolphinscheduler.api.utils.PageInfo; |
|
||||||
import org.apache.dolphinscheduler.api.utils.Result; |
|
||||||
import org.apache.dolphinscheduler.common.constants.Constants; |
|
||||||
import org.apache.dolphinscheduler.common.enums.UserType; |
|
||||||
import org.apache.dolphinscheduler.common.utils.FileUtils; |
|
||||||
import org.apache.dolphinscheduler.common.utils.PropertyUtils; |
|
||||||
import org.apache.dolphinscheduler.dao.entity.Tenant; |
|
||||||
import org.apache.dolphinscheduler.dao.entity.User; |
|
||||||
import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionMapper; |
|
||||||
import org.apache.dolphinscheduler.dao.mapper.TenantMapper; |
|
||||||
import org.apache.dolphinscheduler.dao.mapper.UdfFuncMapper; |
|
||||||
import org.apache.dolphinscheduler.dao.mapper.UserMapper; |
|
||||||
import org.apache.dolphinscheduler.plugin.storage.api.StorageEntity; |
|
||||||
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperate; |
|
||||||
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
|
||||||
|
|
||||||
import org.apache.commons.collections4.CollectionUtils; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.nio.file.Path; |
|
||||||
import java.nio.file.Paths; |
|
||||||
import java.time.LocalDateTime; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.Collections; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Map; |
|
||||||
import java.util.Random; |
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterEach; |
|
||||||
import org.junit.jupiter.api.Assertions; |
|
||||||
import org.junit.jupiter.api.BeforeEach; |
|
||||||
import org.junit.jupiter.api.Test; |
|
||||||
import org.junit.jupiter.api.extension.ExtendWith; |
|
||||||
import org.mockito.InjectMocks; |
|
||||||
import org.mockito.Mock; |
|
||||||
import org.mockito.MockedStatic; |
|
||||||
import org.mockito.Mockito; |
|
||||||
import org.mockito.junit.jupiter.MockitoExtension; |
|
||||||
import org.mockito.junit.jupiter.MockitoSettings; |
|
||||||
import org.mockito.quality.Strictness; |
|
||||||
import org.springframework.mock.web.MockMultipartFile; |
|
||||||
|
|
||||||
import com.google.common.io.Files; |
|
||||||
|
|
||||||
/** |
|
||||||
* resources service test |
|
||||||
*/ |
|
||||||
@ExtendWith(MockitoExtension.class) |
|
||||||
@MockitoSettings(strictness = Strictness.LENIENT) |
|
||||||
public class ResourcesServiceTest { |
|
||||||
|
|
||||||
private static final String basePath = "/dolphinscheduler"; |
|
||||||
private static final String tenantCode = "123"; |
|
||||||
private static final String tenantFileResourceDir = "/dolphinscheduler/123/resources/"; |
|
||||||
private static final String tenantUdfResourceDir = "/dolphinscheduler/123/udfs/"; |
|
||||||
|
|
||||||
@InjectMocks |
|
||||||
private ResourcesServiceImpl resourcesService; |
|
||||||
|
|
||||||
@Mock |
|
||||||
private TenantMapper tenantMapper; |
|
||||||
|
|
||||||
@Mock |
|
||||||
private StorageOperate storageOperate; |
|
||||||
|
|
||||||
@Mock |
|
||||||
private UserMapper userMapper; |
|
||||||
|
|
||||||
@Mock |
|
||||||
private UdfFuncMapper udfFunctionMapper; |
|
||||||
|
|
||||||
@Mock |
|
||||||
private ProcessDefinitionMapper processDefinitionMapper; |
|
||||||
|
|
||||||
@Mock |
|
||||||
private ResourcePermissionCheckService resourcePermissionCheckService; |
|
||||||
|
|
||||||
private MockedStatic<FileUtils> mockedStaticFileUtils; |
|
||||||
|
|
||||||
private MockedStatic<Files> mockedStaticFiles; |
|
||||||
|
|
||||||
private MockedStatic<org.apache.dolphinscheduler.api.utils.FileUtils> mockedStaticDolphinschedulerFileUtils; |
|
||||||
|
|
||||||
private MockedStatic<PropertyUtils> mockedStaticPropertyUtils; |
|
||||||
|
|
||||||
private MockedStatic<Paths> mockedStaticPaths; |
|
||||||
|
|
||||||
private MockedStatic<java.nio.file.Files> filesMockedStatic; |
|
||||||
|
|
||||||
private Exception exception; |
|
||||||
|
|
||||||
@BeforeEach |
|
||||||
public void setUp() { |
|
||||||
mockedStaticFileUtils = Mockito.mockStatic(FileUtils.class); |
|
||||||
mockedStaticFiles = Mockito.mockStatic(Files.class); |
|
||||||
mockedStaticDolphinschedulerFileUtils = |
|
||||||
Mockito.mockStatic(org.apache.dolphinscheduler.api.utils.FileUtils.class); |
|
||||||
|
|
||||||
mockedStaticPropertyUtils = Mockito.mockStatic(PropertyUtils.class); |
|
||||||
mockedStaticPaths = Mockito.mockStatic(Paths.class); |
|
||||||
filesMockedStatic = Mockito.mockStatic(java.nio.file.Files.class); |
|
||||||
} |
|
||||||
|
|
||||||
@AfterEach |
|
||||||
public void after() { |
|
||||||
mockedStaticFileUtils.close(); |
|
||||||
mockedStaticFiles.close(); |
|
||||||
mockedStaticDolphinschedulerFileUtils.close(); |
|
||||||
mockedStaticPropertyUtils.close(); |
|
||||||
mockedStaticPaths.close(); |
|
||||||
filesMockedStatic.close(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testCreateResource() { |
|
||||||
User user = new User(); |
|
||||||
user.setId(1); |
|
||||||
user.setUserType(UserType.GENERAL_USER); |
|
||||||
|
|
||||||
// CURRENT_LOGIN_USER_TENANT_NOT_EXIST
|
|
||||||
when(userMapper.selectById(user.getId())).thenReturn(getUser()); |
|
||||||
when(tenantMapper.queryById(1)).thenReturn(null); |
|
||||||
ServiceException serviceException = Assertions.assertThrows(ServiceException.class, |
|
||||||
() -> resourcesService.uploadResource(user, "ResourcesServiceTest", ResourceType.FILE, |
|
||||||
new MockMultipartFile("test.pdf", "test.pdf", "pdf", "test".getBytes()), "/")); |
|
||||||
assertEquals(Status.CURRENT_LOGIN_USER_TENANT_NOT_EXIST.getMsg(), serviceException.getMessage()); |
|
||||||
|
|
||||||
// set tenant for user
|
|
||||||
user.setTenantId(1); |
|
||||||
when(tenantMapper.queryById(1)).thenReturn(getTenant()); |
|
||||||
when(storageOperate.getDir(ResourceType.ALL, tenantCode)).thenReturn(basePath); |
|
||||||
|
|
||||||
// ILLEGAL_RESOURCE_FILE
|
|
||||||
String illegal_path = "/dolphinscheduler/123/../"; |
|
||||||
serviceException = Assertions.assertThrows(ServiceException.class, |
|
||||||
() -> { |
|
||||||
MockMultipartFile mockMultipartFile = new MockMultipartFile("test.pdf", "".getBytes()); |
|
||||||
resourcesService.uploadResource(user, "ResourcesServiceTest", ResourceType.FILE, |
|
||||||
mockMultipartFile, illegal_path); |
|
||||||
}); |
|
||||||
assertEquals(new ServiceException(Status.ILLEGAL_RESOURCE_PATH, illegal_path), serviceException); |
|
||||||
|
|
||||||
// RESOURCE_FILE_IS_EMPTY
|
|
||||||
MockMultipartFile mockMultipartFile = new MockMultipartFile("test.pdf", "".getBytes()); |
|
||||||
Result result = resourcesService.uploadResource(user, "ResourcesServiceTest", ResourceType.FILE, |
|
||||||
mockMultipartFile, tenantFileResourceDir); |
|
||||||
assertEquals(Status.RESOURCE_FILE_IS_EMPTY.getMsg(), result.getMsg()); |
|
||||||
|
|
||||||
// RESOURCE_SUFFIX_FORBID_CHANGE
|
|
||||||
mockMultipartFile = new MockMultipartFile("test.pdf", "test.pdf", "pdf", "test".getBytes()); |
|
||||||
when(Files.getFileExtension("test.pdf")).thenReturn("pdf"); |
|
||||||
when(Files.getFileExtension("ResourcesServiceTest.jar")).thenReturn("jar"); |
|
||||||
result = resourcesService.uploadResource(user, "ResourcesServiceTest.jar", ResourceType.FILE, mockMultipartFile, |
|
||||||
tenantFileResourceDir); |
|
||||||
assertEquals(Status.RESOURCE_SUFFIX_FORBID_CHANGE.getMsg(), result.getMsg()); |
|
||||||
|
|
||||||
// UDF_RESOURCE_SUFFIX_NOT_JAR
|
|
||||||
mockMultipartFile = |
|
||||||
new MockMultipartFile("ResourcesServiceTest.pdf", "ResourcesServiceTest.pdf", "pdf", "test".getBytes()); |
|
||||||
when(Files.getFileExtension("ResourcesServiceTest.pdf")).thenReturn("pdf"); |
|
||||||
result = resourcesService.uploadResource(user, "ResourcesServiceTest.pdf", ResourceType.UDF, mockMultipartFile, |
|
||||||
tenantUdfResourceDir); |
|
||||||
assertEquals(Status.UDF_RESOURCE_SUFFIX_NOT_JAR.getMsg(), result.getMsg()); |
|
||||||
|
|
||||||
// FULL_FILE_NAME_TOO_LONG
|
|
||||||
String tooLongFileName = getRandomStringWithLength(Constants.RESOURCE_FULL_NAME_MAX_LENGTH) + ".pdf"; |
|
||||||
mockMultipartFile = new MockMultipartFile(tooLongFileName, tooLongFileName, "pdf", "test".getBytes()); |
|
||||||
when(Files.getFileExtension(tooLongFileName)).thenReturn("pdf"); |
|
||||||
|
|
||||||
// '/databasePath/tenantCode/RESOURCE/'
|
|
||||||
when(storageOperate.getResDir(tenantCode)).thenReturn(tenantFileResourceDir); |
|
||||||
result = resourcesService.uploadResource(user, tooLongFileName, ResourceType.FILE, mockMultipartFile, |
|
||||||
tenantFileResourceDir); |
|
||||||
assertEquals(Status.RESOURCE_FULL_NAME_TOO_LONG_ERROR.getMsg(), result.getMsg()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testCreateDirecotry() throws IOException { |
|
||||||
User user = new User(); |
|
||||||
user.setId(1); |
|
||||||
user.setUserType(UserType.GENERAL_USER); |
|
||||||
|
|
||||||
String fileName = "directoryTest"; |
|
||||||
// RESOURCE_EXIST
|
|
||||||
user.setId(1); |
|
||||||
user.setTenantId(1); |
|
||||||
when(tenantMapper.queryById(1)).thenReturn(getTenant()); |
|
||||||
when(userMapper.selectById(user.getId())).thenReturn(getUser()); |
|
||||||
when(storageOperate.getDir(ResourceType.ALL, tenantCode)).thenReturn(basePath); |
|
||||||
when(storageOperate.getResDir(tenantCode)).thenReturn(tenantFileResourceDir); |
|
||||||
when(storageOperate.exists(tenantFileResourceDir + fileName)).thenReturn(true); |
|
||||||
Result result = resourcesService.createDirectory(user, fileName, ResourceType.FILE, -1, tenantFileResourceDir); |
|
||||||
assertEquals(Status.RESOURCE_EXIST.getMsg(), result.getMsg()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testUpdateResource() throws Exception { |
|
||||||
User user = new User(); |
|
||||||
user.setId(1); |
|
||||||
user.setUserType(UserType.GENERAL_USER); |
|
||||||
user.setTenantId(1); |
|
||||||
|
|
||||||
when(userMapper.selectById(user.getId())).thenReturn(getUser()); |
|
||||||
when(tenantMapper.queryById(1)).thenReturn(getTenant()); |
|
||||||
when(storageOperate.getDir(ResourceType.ALL, tenantCode)).thenReturn(basePath); |
|
||||||
when(storageOperate.getResDir(tenantCode)).thenReturn(tenantFileResourceDir); |
|
||||||
|
|
||||||
// TENANT_NOT_EXIST
|
|
||||||
when(tenantMapper.queryById(Mockito.anyInt())).thenReturn(null); |
|
||||||
Assertions.assertThrows(ServiceException.class, () -> resourcesService.updateResource(user, |
|
||||||
"ResourcesServiceTest1.jar", "", "ResourcesServiceTest", ResourceType.UDF, null)); |
|
||||||
|
|
||||||
// USER_NO_OPERATION_PERM
|
|
||||||
user.setUserType(UserType.GENERAL_USER); |
|
||||||
// tenant who have access to resource is 123,
|
|
||||||
Tenant tenantWNoPermission = new Tenant(); |
|
||||||
tenantWNoPermission.setTenantCode("321"); |
|
||||||
when(tenantMapper.queryById(1)).thenReturn(tenantWNoPermission); |
|
||||||
when(storageOperate.getDir(ResourceType.ALL, "321")).thenReturn(basePath); |
|
||||||
|
|
||||||
String fileName = "ResourcesServiceTest"; |
|
||||||
Result result = resourcesService.updateResource(user, tenantFileResourceDir + fileName, |
|
||||||
tenantCode, fileName, ResourceType.FILE, null); |
|
||||||
assertEquals(Status.NO_CURRENT_OPERATING_PERMISSION.getMsg(), result.getMsg()); |
|
||||||
|
|
||||||
// SUCCESS
|
|
||||||
when(tenantMapper.queryById(1)).thenReturn(getTenant()); |
|
||||||
when(storageOperate.exists(Mockito.any())).thenReturn(false); |
|
||||||
|
|
||||||
when(storageOperate.getDir(ResourceType.FILE, tenantCode)).thenReturn(tenantFileResourceDir); |
|
||||||
when(storageOperate.getFileStatus(tenantFileResourceDir + fileName, |
|
||||||
tenantFileResourceDir, tenantCode, ResourceType.FILE)) |
|
||||||
.thenReturn(getStorageEntityResource(fileName)); |
|
||||||
result = resourcesService.updateResource(user, tenantFileResourceDir + fileName, |
|
||||||
tenantCode, fileName, ResourceType.FILE, null); |
|
||||||
assertEquals(Status.SUCCESS.getMsg(), result.getMsg()); |
|
||||||
|
|
||||||
// Tests for udf resources.
|
|
||||||
fileName = "ResourcesServiceTest.jar"; |
|
||||||
when(storageOperate.getDir(ResourceType.UDF, tenantCode)).thenReturn(tenantUdfResourceDir); |
|
||||||
when(storageOperate.exists(tenantUdfResourceDir + fileName)).thenReturn(true); |
|
||||||
when(storageOperate.getFileStatus(tenantUdfResourceDir + fileName, tenantUdfResourceDir, tenantCode, |
|
||||||
ResourceType.UDF)) |
|
||||||
.thenReturn(getStorageEntityUdfResource(fileName)); |
|
||||||
result = resourcesService.updateResource(user, tenantUdfResourceDir + fileName, |
|
||||||
tenantCode, fileName, ResourceType.UDF, null); |
|
||||||
assertEquals(Status.SUCCESS.getMsg(), result.getMsg()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testQueryResourceListPaging() throws Exception { |
|
||||||
User loginUser = new User(); |
|
||||||
loginUser.setId(1); |
|
||||||
loginUser.setTenantId(1); |
|
||||||
loginUser.setTenantCode("tenant1"); |
|
||||||
loginUser.setUserType(UserType.ADMIN_USER); |
|
||||||
|
|
||||||
String fileName = "ResourcesServiceTest"; |
|
||||||
List<StorageEntity> mockResList = new ArrayList<>(); |
|
||||||
mockResList.add(getStorageEntityResource(fileName)); |
|
||||||
List<User> mockUserList = new ArrayList<>(); |
|
||||||
mockUserList.add(getUser()); |
|
||||||
when(userMapper.selectList(null)).thenReturn(mockUserList); |
|
||||||
when(userMapper.selectById(getUser().getId())).thenReturn(getUser()); |
|
||||||
when(tenantMapper.queryById(getUser().getTenantId())).thenReturn(getTenant()); |
|
||||||
when(storageOperate.getResDir(tenantCode)).thenReturn(tenantFileResourceDir); |
|
||||||
when(storageOperate.listFilesStatus(tenantFileResourceDir, tenantFileResourceDir, |
|
||||||
tenantCode, ResourceType.FILE)).thenReturn(mockResList); |
|
||||||
|
|
||||||
Result result = resourcesService.queryResourceListPaging(loginUser, "", "", ResourceType.FILE, "Test", 1, 10); |
|
||||||
assertEquals(Status.SUCCESS.getCode(), (int) result.getCode()); |
|
||||||
PageInfo pageInfo = (PageInfo) result.getData(); |
|
||||||
Assertions.assertTrue(CollectionUtils.isNotEmpty(pageInfo.getTotalList())); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testQueryResourceList() { |
|
||||||
User loginUser = getUser(); |
|
||||||
String fileName = "ResourcesServiceTest"; |
|
||||||
|
|
||||||
when(userMapper.selectList(null)).thenReturn(Collections.singletonList(loginUser)); |
|
||||||
when(userMapper.selectById(loginUser.getId())).thenReturn(loginUser); |
|
||||||
when(tenantMapper.queryById(Mockito.anyInt())).thenReturn(getTenant()); |
|
||||||
when(storageOperate.getDir(ResourceType.ALL, tenantCode)).thenReturn(basePath); |
|
||||||
when(storageOperate.getDir(ResourceType.FILE, tenantCode)).thenReturn(tenantFileResourceDir); |
|
||||||
when(storageOperate.getResDir(tenantCode)).thenReturn(tenantFileResourceDir); |
|
||||||
when(storageOperate.listFilesStatusRecursively(tenantFileResourceDir, |
|
||||||
tenantFileResourceDir, tenantCode, ResourceType.FILE)) |
|
||||||
.thenReturn(Collections.singletonList(getStorageEntityResource(fileName))); |
|
||||||
Map<String, Object> result = |
|
||||||
resourcesService.queryResourceList(loginUser, ResourceType.FILE, tenantFileResourceDir); |
|
||||||
assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); |
|
||||||
List<ResourceComponent> resourceList = (List<ResourceComponent>) result.get(Constants.DATA_LIST); |
|
||||||
Assertions.assertTrue(CollectionUtils.isNotEmpty(resourceList)); |
|
||||||
|
|
||||||
// test udf
|
|
||||||
when(storageOperate.getDir(ResourceType.UDF, tenantCode)).thenReturn(tenantUdfResourceDir); |
|
||||||
when(storageOperate.getUdfDir(tenantCode)).thenReturn(tenantUdfResourceDir); |
|
||||||
when(storageOperate.listFilesStatusRecursively(tenantUdfResourceDir, tenantUdfResourceDir, |
|
||||||
tenantCode, ResourceType.UDF)).thenReturn(Arrays.asList(getStorageEntityUdfResource("test.jar"))); |
|
||||||
loginUser.setUserType(UserType.GENERAL_USER); |
|
||||||
result = resourcesService.queryResourceList(loginUser, ResourceType.UDF, tenantUdfResourceDir); |
|
||||||
assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); |
|
||||||
resourceList = (List<ResourceComponent>) result.get(Constants.DATA_LIST); |
|
||||||
Assertions.assertTrue(CollectionUtils.isNotEmpty(resourceList)); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testDelete() throws Exception { |
|
||||||
User loginUser = new User(); |
|
||||||
loginUser.setId(0); |
|
||||||
loginUser.setUserType(UserType.GENERAL_USER); |
|
||||||
|
|
||||||
// TENANT_NOT_EXIST
|
|
||||||
loginUser.setUserType(UserType.ADMIN_USER); |
|
||||||
loginUser.setTenantId(2); |
|
||||||
when(userMapper.selectById(loginUser.getId())).thenReturn(loginUser); |
|
||||||
Assertions.assertThrows(ServiceException.class, () -> resourcesService.delete(loginUser, "", "")); |
|
||||||
|
|
||||||
// RESOURCE_NOT_EXIST
|
|
||||||
String fileName = "ResourcesServiceTest"; |
|
||||||
when(tenantMapper.queryById(Mockito.anyInt())).thenReturn(getTenant()); |
|
||||||
when(storageOperate.getDir(ResourceType.ALL, tenantCode)).thenReturn(basePath); |
|
||||||
when(storageOperate.getResDir(getTenant().getTenantCode())).thenReturn(tenantFileResourceDir); |
|
||||||
when(storageOperate.getFileStatus(tenantFileResourceDir + fileName, tenantFileResourceDir, tenantCode, null)) |
|
||||||
.thenReturn(getStorageEntityResource(fileName)); |
|
||||||
Result result = resourcesService.delete(loginUser, tenantFileResourceDir + "ResNotExist", tenantCode); |
|
||||||
assertEquals(Status.RESOURCE_NOT_EXIST.getMsg(), result.getMsg()); |
|
||||||
|
|
||||||
// SUCCESS
|
|
||||||
loginUser.setTenantId(1); |
|
||||||
result = resourcesService.delete(loginUser, tenantFileResourceDir + fileName, tenantCode); |
|
||||||
assertEquals(Status.SUCCESS.getMsg(), result.getMsg()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testVerifyResourceName() throws IOException { |
|
||||||
User user = new User(); |
|
||||||
user.setId(1); |
|
||||||
user.setUserType(UserType.GENERAL_USER); |
|
||||||
|
|
||||||
String fileName = "ResourcesServiceTest"; |
|
||||||
when(storageOperate.exists(tenantFileResourceDir + fileName)).thenReturn(true); |
|
||||||
|
|
||||||
Result result = resourcesService.verifyResourceName(tenantFileResourceDir + fileName, ResourceType.FILE, user); |
|
||||||
assertEquals(Status.RESOURCE_EXIST.getMsg(), result.getMsg()); |
|
||||||
|
|
||||||
// RESOURCE_FILE_EXIST
|
|
||||||
result = resourcesService.verifyResourceName(tenantFileResourceDir + fileName, ResourceType.FILE, user); |
|
||||||
Assertions.assertTrue(Status.RESOURCE_EXIST.getCode() == result.getCode()); |
|
||||||
|
|
||||||
// SUCCESS
|
|
||||||
result = resourcesService.verifyResourceName("test2", ResourceType.FILE, user); |
|
||||||
assertEquals(Status.SUCCESS.getMsg(), result.getMsg()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testReadResource() throws IOException { |
|
||||||
// RESOURCE_NOT_EXIST
|
|
||||||
when(userMapper.selectById(getUser().getId())).thenReturn(getUser()); |
|
||||||
when(tenantMapper.queryById(getUser().getTenantId())).thenReturn(getTenant()); |
|
||||||
Result result = resourcesService.readResource(getUser(), "", "", 1, 10); |
|
||||||
assertEquals(Status.RESOURCE_FILE_NOT_EXIST.getCode(), (int) result.getCode()); |
|
||||||
|
|
||||||
// RESOURCE_SUFFIX_NOT_SUPPORT_VIEW
|
|
||||||
when(FileUtils.getResourceViewSuffixes()).thenReturn("class"); |
|
||||||
result = resourcesService.readResource(getUser(), "", "", 1, 10); |
|
||||||
assertEquals(Status.RESOURCE_SUFFIX_NOT_SUPPORT_VIEW.getMsg(), result.getMsg()); |
|
||||||
|
|
||||||
// USER_NOT_EXIST
|
|
||||||
when(userMapper.selectById(getUser().getId())).thenReturn(null); |
|
||||||
when(FileUtils.getResourceViewSuffixes()).thenReturn("jar"); |
|
||||||
when(Files.getFileExtension("ResourcesServiceTest.jar")).thenReturn("jar"); |
|
||||||
result = resourcesService.readResource(getUser(), "", "", 1, 10); |
|
||||||
assertEquals(Status.USER_NOT_EXIST.getCode(), (int) result.getCode()); |
|
||||||
|
|
||||||
// TENANT_NOT_EXIST
|
|
||||||
when(userMapper.selectById(getUser().getId())).thenReturn(getUser()); |
|
||||||
when(tenantMapper.queryById(getUser().getTenantId())).thenReturn(null); |
|
||||||
Assertions.assertThrows(ServiceException.class, () -> resourcesService.readResource(getUser(), "", "", 1, 10)); |
|
||||||
|
|
||||||
// SUCCESS
|
|
||||||
when(FileUtils.getResourceViewSuffixes()).thenReturn("jar,sh"); |
|
||||||
when(storageOperate.getDir(ResourceType.ALL, tenantCode)).thenReturn(basePath); |
|
||||||
when(storageOperate.getResDir(getTenant().getTenantCode())).thenReturn(tenantFileResourceDir); |
|
||||||
when(userMapper.selectById(getUser().getId())).thenReturn(getUser()); |
|
||||||
when(tenantMapper.queryById(getUser().getTenantId())).thenReturn(getTenant()); |
|
||||||
when(storageOperate.exists(Mockito.any())).thenReturn(true); |
|
||||||
when(storageOperate.vimFile(Mockito.any(), Mockito.any(), eq(1), eq(10))).thenReturn(getContent()); |
|
||||||
when(Files.getFileExtension("/dolphinscheduler/123/resources/test.jar")).thenReturn("jar"); |
|
||||||
result = resourcesService.readResource(getUser(), "/dolphinscheduler/123/resources/test.jar", tenantCode, 1, |
|
||||||
10); |
|
||||||
assertEquals(Status.SUCCESS.getMsg(), result.getMsg()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testCreateOrUpdateResource() throws Exception { |
|
||||||
User user = getUser(); |
|
||||||
when(userMapper.queryByUserNameAccurately(user.getUserName())).thenReturn(getUser()); |
|
||||||
|
|
||||||
// RESOURCE_SUFFIX_NOT_SUPPORT_VIEW
|
|
||||||
exception = Assertions.assertThrows(IllegalArgumentException.class, |
|
||||||
() -> resourcesService.createOrUpdateResource(user.getUserName(), "filename", "my-content")); |
|
||||||
Assertions.assertTrue( |
|
||||||
exception.getMessage().contains("Not allow create or update resources without extension name")); |
|
||||||
|
|
||||||
// SUCCESS
|
|
||||||
String fileName = "ResourcesServiceTest"; |
|
||||||
when(storageOperate.getResDir(user.getTenantCode())).thenReturn(tenantFileResourceDir); |
|
||||||
when(FileUtils.getUploadFilename(Mockito.anyString(), Mockito.anyString())).thenReturn("test"); |
|
||||||
when(FileUtils.writeContent2File(Mockito.anyString(), Mockito.anyString())).thenReturn(true); |
|
||||||
when(storageOperate.getFileStatus(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any())) |
|
||||||
.thenReturn(getStorageEntityResource(fileName)); |
|
||||||
StorageEntity storageEntity = |
|
||||||
resourcesService.createOrUpdateResource(user.getUserName(), "filename.txt", "my-content"); |
|
||||||
Assertions.assertNotNull(storageEntity); |
|
||||||
assertEquals(tenantFileResourceDir + fileName, storageEntity.getFullName()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testUpdateResourceContent() throws Exception { |
|
||||||
// RESOURCE_PATH_ILLEGAL
|
|
||||||
when(userMapper.selectById(getUser().getId())).thenReturn(getUser()); |
|
||||||
when(tenantMapper.queryById(1)).thenReturn(getTenant()); |
|
||||||
when(storageOperate.getResDir(Mockito.anyString())).thenReturn("/tmp"); |
|
||||||
|
|
||||||
String fileName = "ResourcesServiceTest.jar"; |
|
||||||
ServiceException serviceException = |
|
||||||
Assertions.assertThrows(ServiceException.class, () -> resourcesService.updateResourceContent(getUser(), |
|
||||||
tenantFileResourceDir + fileName, tenantCode, "content")); |
|
||||||
assertEquals(new ServiceException(Status.ILLEGAL_RESOURCE_PATH, tenantFileResourceDir + fileName), |
|
||||||
serviceException); |
|
||||||
|
|
||||||
// RESOURCE_NOT_EXIST
|
|
||||||
when(storageOperate.getDir(ResourceType.ALL, tenantCode)).thenReturn(basePath); |
|
||||||
when(storageOperate.getResDir(Mockito.anyString())).thenReturn(tenantFileResourceDir); |
|
||||||
when(storageOperate.getFileStatus(tenantFileResourceDir + fileName, "", tenantCode, ResourceType.FILE)) |
|
||||||
.thenReturn(null); |
|
||||||
Result result = resourcesService.updateResourceContent(getUser(), tenantFileResourceDir + fileName, tenantCode, |
|
||||||
"content"); |
|
||||||
assertEquals(Status.RESOURCE_NOT_EXIST.getMsg(), result.getMsg()); |
|
||||||
|
|
||||||
// RESOURCE_SUFFIX_NOT_SUPPORT_VIEW
|
|
||||||
when(FileUtils.getResourceViewSuffixes()).thenReturn("class"); |
|
||||||
when(storageOperate.getFileStatus(tenantFileResourceDir, "", tenantCode, ResourceType.FILE)) |
|
||||||
.thenReturn(getStorageEntityResource(fileName)); |
|
||||||
|
|
||||||
result = resourcesService.updateResourceContent(getUser(), tenantFileResourceDir, tenantCode, |
|
||||||
"content"); |
|
||||||
assertEquals(Status.RESOURCE_SUFFIX_NOT_SUPPORT_VIEW.getMsg(), result.getMsg()); |
|
||||||
|
|
||||||
// USER_NOT_EXIST
|
|
||||||
when(userMapper.selectById(getUser().getId())).thenReturn(null); |
|
||||||
result = resourcesService.updateResourceContent(getUser(), tenantFileResourceDir + "123.class", |
|
||||||
tenantCode, |
|
||||||
"content"); |
|
||||||
Assertions.assertTrue(Status.USER_NOT_EXIST.getCode() == result.getCode()); |
|
||||||
|
|
||||||
// TENANT_NOT_EXIST
|
|
||||||
when(userMapper.selectById(getUser().getId())).thenReturn(getUser()); |
|
||||||
when(tenantMapper.queryById(1)).thenReturn(null); |
|
||||||
Assertions.assertThrows(ServiceException.class, () -> resourcesService.updateResourceContent(getUser(), |
|
||||||
tenantFileResourceDir + fileName, tenantCode, "content")); |
|
||||||
|
|
||||||
// SUCCESS
|
|
||||||
when(storageOperate.getFileStatus(tenantFileResourceDir + fileName, "", tenantCode, |
|
||||||
ResourceType.FILE)).thenReturn(getStorageEntityResource(fileName)); |
|
||||||
|
|
||||||
when(Files.getFileExtension(Mockito.anyString())).thenReturn("jar"); |
|
||||||
when(FileUtils.getResourceViewSuffixes()).thenReturn("jar"); |
|
||||||
when(userMapper.selectById(getUser().getId())).thenReturn(getUser()); |
|
||||||
when(tenantMapper.queryById(1)).thenReturn(getTenant()); |
|
||||||
when(FileUtils.getUploadFilename(Mockito.anyString(), Mockito.anyString())).thenReturn("test"); |
|
||||||
when(FileUtils.writeContent2File(Mockito.anyString(), Mockito.anyString())).thenReturn(true); |
|
||||||
result = resourcesService.updateResourceContent(getUser(), |
|
||||||
tenantFileResourceDir + fileName, tenantCode, "content"); |
|
||||||
assertEquals(Status.SUCCESS.getMsg(), result.getMsg()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testDownloadResource() throws IOException { |
|
||||||
when(tenantMapper.queryById(1)).thenReturn(getTenant()); |
|
||||||
when(userMapper.selectById(1)).thenReturn(getUser()); |
|
||||||
org.springframework.core.io.Resource resourceMock = Mockito.mock(org.springframework.core.io.Resource.class); |
|
||||||
Path path = Mockito.mock(Path.class); |
|
||||||
when(Paths.get(Mockito.any())).thenReturn(path); |
|
||||||
when(java.nio.file.Files.size(Mockito.any())).thenReturn(1L); |
|
||||||
// resource null
|
|
||||||
org.springframework.core.io.Resource resource = resourcesService.downloadResource(getUser(), ""); |
|
||||||
Assertions.assertNull(resource); |
|
||||||
|
|
||||||
when(org.apache.dolphinscheduler.api.utils.FileUtils.file2Resource(Mockito.any())).thenReturn(resourceMock); |
|
||||||
resource = resourcesService.downloadResource(getUser(), ""); |
|
||||||
Assertions.assertNotNull(resource); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testDeleteDataTransferData() throws Exception { |
|
||||||
User user = getUser(); |
|
||||||
when(userMapper.selectById(user.getId())).thenReturn(getUser()); |
|
||||||
when(tenantMapper.queryById(user.getTenantId())).thenReturn(getTenant()); |
|
||||||
|
|
||||||
StorageEntity storageEntity1 = Mockito.mock(StorageEntity.class); |
|
||||||
StorageEntity storageEntity2 = Mockito.mock(StorageEntity.class); |
|
||||||
StorageEntity storageEntity3 = Mockito.mock(StorageEntity.class); |
|
||||||
StorageEntity storageEntity4 = Mockito.mock(StorageEntity.class); |
|
||||||
StorageEntity storageEntity5 = Mockito.mock(StorageEntity.class); |
|
||||||
|
|
||||||
when(storageEntity1.getFullName()).thenReturn("DATA_TRANSFER/20220101"); |
|
||||||
when(storageEntity2.getFullName()).thenReturn("DATA_TRANSFER/20220102"); |
|
||||||
when(storageEntity3.getFullName()).thenReturn("DATA_TRANSFER/20220103"); |
|
||||||
when(storageEntity4.getFullName()).thenReturn("DATA_TRANSFER/20220104"); |
|
||||||
when(storageEntity5.getFullName()).thenReturn("DATA_TRANSFER/20220105"); |
|
||||||
|
|
||||||
List<StorageEntity> storageEntityList = new ArrayList<>(); |
|
||||||
storageEntityList.add(storageEntity1); |
|
||||||
storageEntityList.add(storageEntity2); |
|
||||||
storageEntityList.add(storageEntity3); |
|
||||||
storageEntityList.add(storageEntity4); |
|
||||||
storageEntityList.add(storageEntity5); |
|
||||||
|
|
||||||
when(storageOperate.listFilesStatus(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) |
|
||||||
.thenReturn(storageEntityList); |
|
||||||
|
|
||||||
LocalDateTime localDateTime = LocalDateTime.of(2022, 1, 5, 0, 0, 0); |
|
||||||
try (MockedStatic<LocalDateTime> mockHook = Mockito.mockStatic(LocalDateTime.class)) { |
|
||||||
mockHook.when(LocalDateTime::now).thenReturn(localDateTime); |
|
||||||
DeleteDataTransferResponse response = resourcesService.deleteDataTransferData(user, 3); |
|
||||||
|
|
||||||
assertEquals(response.getSuccessList().size(), 2); |
|
||||||
assertEquals(response.getSuccessList().get(0), "DATA_TRANSFER/20220101"); |
|
||||||
assertEquals(response.getSuccessList().get(1), "DATA_TRANSFER/20220102"); |
|
||||||
} |
|
||||||
|
|
||||||
try (MockedStatic<LocalDateTime> mockHook = Mockito.mockStatic(LocalDateTime.class)) { |
|
||||||
mockHook.when(LocalDateTime::now).thenReturn(localDateTime); |
|
||||||
DeleteDataTransferResponse response = resourcesService.deleteDataTransferData(user, 0); |
|
||||||
assertEquals(response.getSuccessList().size(), 5); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testCatFile() throws IOException { |
|
||||||
// SUCCESS
|
|
||||||
List<String> list = storageOperate.vimFile(Mockito.any(), Mockito.anyString(), eq(1), eq(10)); |
|
||||||
Assertions.assertNotNull(list); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
void testQueryBaseDir() throws Exception { |
|
||||||
User user = getUser(); |
|
||||||
String fileName = "ResourcesServiceTest.jar"; |
|
||||||
when(userMapper.selectById(user.getId())).thenReturn(getUser()); |
|
||||||
when(tenantMapper.queryById(user.getTenantId())).thenReturn(getTenant()); |
|
||||||
when(storageOperate.getDir(ResourceType.FILE, tenantCode)).thenReturn(tenantFileResourceDir); |
|
||||||
when(storageOperate.getFileStatus(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), |
|
||||||
Mockito.any())).thenReturn(getStorageEntityResource(fileName)); |
|
||||||
Result<Object> result = resourcesService.queryResourceBaseDir(user, ResourceType.FILE); |
|
||||||
assertEquals(Status.SUCCESS.getMsg(), result.getMsg()); |
|
||||||
} |
|
||||||
|
|
||||||
private Tenant getTenant() { |
|
||||||
Tenant tenant = new Tenant(); |
|
||||||
tenant.setTenantCode(tenantCode); |
|
||||||
return tenant; |
|
||||||
} |
|
||||||
|
|
||||||
private User getUser() { |
|
||||||
User user = new User(); |
|
||||||
user.setId(1); |
|
||||||
user.setUserType(UserType.GENERAL_USER); |
|
||||||
user.setTenantId(1); |
|
||||||
user.setTenantCode(tenantCode); |
|
||||||
return user; |
|
||||||
} |
|
||||||
|
|
||||||
private StorageEntity getStorageEntityResource(String fileName) { |
|
||||||
StorageEntity entity = new StorageEntity(); |
|
||||||
entity.setAlias(fileName); |
|
||||||
entity.setFileName(fileName); |
|
||||||
entity.setDirectory(false); |
|
||||||
entity.setUserName(tenantCode); |
|
||||||
entity.setType(ResourceType.FILE); |
|
||||||
entity.setFullName(tenantFileResourceDir + fileName); |
|
||||||
return entity; |
|
||||||
} |
|
||||||
|
|
||||||
private StorageEntity getStorageEntityUdfResource(String fileName) { |
|
||||||
StorageEntity entity = new StorageEntity(); |
|
||||||
entity.setAlias(fileName); |
|
||||||
entity.setFileName(fileName); |
|
||||||
entity.setDirectory(false); |
|
||||||
entity.setUserName(tenantCode); |
|
||||||
entity.setType(ResourceType.UDF); |
|
||||||
entity.setFullName(tenantUdfResourceDir + fileName); |
|
||||||
|
|
||||||
return entity; |
|
||||||
} |
|
||||||
|
|
||||||
private List<String> getContent() { |
|
||||||
List<String> contentList = new ArrayList<>(); |
|
||||||
contentList.add("test"); |
|
||||||
return contentList; |
|
||||||
} |
|
||||||
|
|
||||||
private List<Map<String, Object>> getResources() { |
|
||||||
List<Map<String, Object>> resources = new ArrayList<>(); |
|
||||||
Map<String, Object> resource = new HashMap<>(); |
|
||||||
resource.put("id", 1); |
|
||||||
resource.put("resource_ids", "1"); |
|
||||||
resources.add(resource); |
|
||||||
return resources; |
|
||||||
} |
|
||||||
|
|
||||||
private static String getRandomStringWithLength(int length) { |
|
||||||
Random r = new Random(); |
|
||||||
StringBuilder sb = new StringBuilder(); |
|
||||||
while (sb.length() < length) { |
|
||||||
char c = (char) (r.nextInt(26) + 'a'); |
|
||||||
sb.append(c); |
|
||||||
} |
|
||||||
return sb.toString(); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,136 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import static org.apache.dolphinscheduler.api.AssertionsHelper.assertThrowServiceException; |
||||||
|
import static org.mockito.Mockito.when; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.CreateDirectoryDto; |
||||||
|
import org.apache.dolphinscheduler.common.enums.UserType; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.Tenant; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.ResourceMetadata; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import java.util.Locale; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.junit.jupiter.api.extension.ExtendWith; |
||||||
|
import org.mockito.InjectMocks; |
||||||
|
import org.mockito.Mock; |
||||||
|
import org.mockito.junit.jupiter.MockitoExtension; |
||||||
|
import org.springframework.context.i18n.LocaleContextHolder; |
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class) |
||||||
|
class CreateDirectoryDtoValidatorTest { |
||||||
|
|
||||||
|
@Mock |
||||||
|
private StorageOperator storageOperator; |
||||||
|
|
||||||
|
@Mock |
||||||
|
private TenantDao tenantDao; |
||||||
|
|
||||||
|
@InjectMocks |
||||||
|
private CreateDirectoryDtoValidator createDirectoryDtoValidator; |
||||||
|
|
||||||
|
private static final String BASE_DIRECTORY = "/tmp/dolphinscheduler"; |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
@BeforeEach |
||||||
|
public void setup() { |
||||||
|
when(storageOperator.getStorageBaseDirectory()).thenReturn(BASE_DIRECTORY); |
||||||
|
loginUser = new User(); |
||||||
|
loginUser.setTenantId(1); |
||||||
|
LocaleContextHolder.setLocale(Locale.ENGLISH); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testValidate_notUnderBaseDirectory() { |
||||||
|
CreateDirectoryDto createDirectoryDto = CreateDirectoryDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.directoryAbsolutePath("/tmp") |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: Invalidated resource path: /tmp", |
||||||
|
() -> createDirectoryDtoValidator.validate(createDirectoryDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_directoryPathContainsIllegalSymbolic() { |
||||||
|
CreateDirectoryDto createDirectoryDto = CreateDirectoryDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.directoryAbsolutePath("/tmp/dolphinscheduler/default/resources/..") |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: Invalidated resource path: /tmp/dolphinscheduler/default/resources/..", |
||||||
|
() -> createDirectoryDtoValidator.validate(createDirectoryDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_directoryExist() { |
||||||
|
CreateDirectoryDto createDirectoryDto = CreateDirectoryDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.directoryAbsolutePath("/tmp/dolphinscheduler/default/resources/demo") |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(createDirectoryDto.getDirectoryAbsolutePath())).thenReturn(true); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The resource is already exist: /tmp/dolphinscheduler/default/resources/demo", |
||||||
|
() -> createDirectoryDtoValidator.validate(createDirectoryDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_NoPermission() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("test"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
CreateDirectoryDto createDirectoryDto = CreateDirectoryDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.directoryAbsolutePath("/tmp/dolphinscheduler/default/resources/demo") |
||||||
|
.build(); |
||||||
|
when(storageOperator.getResourceMetaData(createDirectoryDto.getDirectoryAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(createDirectoryDto.getDirectoryAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("demo") |
||||||
|
.isDirectory(true) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
when(storageOperator.exists(createDirectoryDto.getDirectoryAbsolutePath())).thenReturn(false); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The user's tenant is test have no permission to access the resource: /tmp/dolphinscheduler/default/resources/demo", |
||||||
|
() -> createDirectoryDtoValidator.validate(createDirectoryDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_pathNotDirectory() { |
||||||
|
CreateDirectoryDto createDirectoryDto = CreateDirectoryDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.directoryAbsolutePath("/tmp/dolphinscheduler/default/resources/demo.sql") |
||||||
|
.build(); |
||||||
|
loginUser.setUserType(UserType.ADMIN_USER); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The path is not a directory: /tmp/dolphinscheduler/default/resources/demo.sql", |
||||||
|
() -> createDirectoryDtoValidator.validate(createDirectoryDto)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,188 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import static org.apache.dolphinscheduler.api.AssertionsHelper.assertDoesNotThrow; |
||||||
|
import static org.apache.dolphinscheduler.api.AssertionsHelper.assertThrowServiceException; |
||||||
|
import static org.mockito.Mockito.when; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.CreateFileFromContentDto; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.Tenant; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.ResourceMetadata; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import java.util.Locale; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.junit.jupiter.api.extension.ExtendWith; |
||||||
|
import org.mockito.InjectMocks; |
||||||
|
import org.mockito.Mock; |
||||||
|
import org.mockito.junit.jupiter.MockitoExtension; |
||||||
|
import org.springframework.context.i18n.LocaleContextHolder; |
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class) |
||||||
|
class CreateFileFromContentDtoValidatorTest { |
||||||
|
|
||||||
|
@Mock |
||||||
|
private StorageOperator storageOperator; |
||||||
|
|
||||||
|
@Mock |
||||||
|
private TenantDao tenantDao; |
||||||
|
|
||||||
|
@InjectMocks |
||||||
|
private CreateFileFromContentDtoValidator createFileFromContentDtoValidator; |
||||||
|
|
||||||
|
private static final String BASE_DIRECTORY = "/tmp/dolphinscheduler"; |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
@BeforeEach |
||||||
|
public void setup() { |
||||||
|
when(storageOperator.getStorageBaseDirectory()).thenReturn(BASE_DIRECTORY); |
||||||
|
loginUser = new User(); |
||||||
|
loginUser.setTenantId(1); |
||||||
|
LocaleContextHolder.setLocale(Locale.ENGLISH); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testValidate_notUnderBaseDirectory() { |
||||||
|
CreateFileFromContentDto createFileFromContentDto = CreateFileFromContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.fileAbsolutePath("/tmp") |
||||||
|
.fileContent("select * from t") |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: Invalidated resource path: /tmp", |
||||||
|
() -> createFileFromContentDtoValidator.validate(createFileFromContentDto)); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_filePathContainsIllegalSymbolic() { |
||||||
|
CreateFileFromContentDto renameDirectoryDto = CreateFileFromContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.fileAbsolutePath("/tmp/dolphinscheduler/default/resources/..") |
||||||
|
.fileContent("select * from t") |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: Invalidated resource path: /tmp/dolphinscheduler/default/resources/..", |
||||||
|
() -> createFileFromContentDtoValidator.validate(renameDirectoryDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_IsNotFile() { |
||||||
|
CreateFileFromContentDto createFileFromContentDto = CreateFileFromContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.fileAbsolutePath("/tmp/dolphinscheduler/default/resources/a") |
||||||
|
.fileContent("select * from t") |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The path is not a file: /tmp/dolphinscheduler/default/resources/a", |
||||||
|
() -> createFileFromContentDtoValidator.validate(createFileFromContentDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_fileAlreadyExist() { |
||||||
|
CreateFileFromContentDto createFileFromContentDto = CreateFileFromContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.fileAbsolutePath("/tmp/dolphinscheduler/default/resources/a.sql") |
||||||
|
.fileContent("select * from t") |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(createFileFromContentDto.getFileAbsolutePath())).thenReturn(true); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The resource is already exist: /tmp/dolphinscheduler/default/resources/a.sql", |
||||||
|
() -> createFileFromContentDtoValidator.validate(createFileFromContentDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_fileNoPermission() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("test"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
CreateFileFromContentDto createFileFromContentDto = CreateFileFromContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.fileAbsolutePath("/tmp/dolphinscheduler/default/resources/a.sql") |
||||||
|
.fileContent("select * from t") |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(createFileFromContentDto.getFileAbsolutePath())).thenReturn(false); |
||||||
|
when(storageOperator.getResourceMetaData(createFileFromContentDto.getFileAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(createFileFromContentDto.getFileAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("a.sql") |
||||||
|
.isDirectory(false) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The user's tenant is test have no permission to access the resource: /tmp/dolphinscheduler/default/resources/a.sql", |
||||||
|
() -> createFileFromContentDtoValidator.validate(createFileFromContentDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_contentIsInvalidated() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("default"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
CreateFileFromContentDto createFileFromContentDto = CreateFileFromContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.fileAbsolutePath("/tmp/dolphinscheduler/default/resources/a.sql") |
||||||
|
.fileContent("") |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(createFileFromContentDto.getFileAbsolutePath())).thenReturn(false); |
||||||
|
when(storageOperator.getResourceMetaData(createFileFromContentDto.getFileAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(createFileFromContentDto.getFileAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("a.sql") |
||||||
|
.isDirectory(false) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The file content is null", |
||||||
|
() -> createFileFromContentDtoValidator.validate(createFileFromContentDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("default"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
CreateFileFromContentDto createFileFromContentDto = CreateFileFromContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.fileAbsolutePath("/tmp/dolphinscheduler/default/resources/a.sql") |
||||||
|
.fileContent("select * from t") |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(createFileFromContentDto.getFileAbsolutePath())).thenReturn(false); |
||||||
|
when(storageOperator.getResourceMetaData(createFileFromContentDto.getFileAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(createFileFromContentDto.getFileAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("a.sql") |
||||||
|
.isDirectory(false) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
assertDoesNotThrow(() -> createFileFromContentDtoValidator.validate(createFileFromContentDto)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,197 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import static org.apache.dolphinscheduler.api.AssertionsHelper.assertThrowServiceException; |
||||||
|
import static org.mockito.Mockito.when; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.AssertionsHelper; |
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.FetchFileContentDto; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.Tenant; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.ResourceMetadata; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import java.util.Locale; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.junit.jupiter.api.extension.ExtendWith; |
||||||
|
import org.mockito.InjectMocks; |
||||||
|
import org.mockito.Mock; |
||||||
|
import org.mockito.junit.jupiter.MockitoExtension; |
||||||
|
import org.mockito.junit.jupiter.MockitoSettings; |
||||||
|
import org.mockito.quality.Strictness; |
||||||
|
import org.springframework.context.i18n.LocaleContextHolder; |
||||||
|
|
||||||
|
@MockitoSettings(strictness = Strictness.LENIENT) |
||||||
|
@ExtendWith(MockitoExtension.class) |
||||||
|
class FetchFileContentDtoValidatorTest { |
||||||
|
|
||||||
|
@Mock |
||||||
|
private StorageOperator storageOperator; |
||||||
|
|
||||||
|
@Mock |
||||||
|
private TenantDao tenantDao; |
||||||
|
|
||||||
|
@InjectMocks |
||||||
|
private FetchFileContentDtoValidator fetchFileContentDtoValidator; |
||||||
|
|
||||||
|
private static final String BASE_DIRECTORY = "/tmp/dolphinscheduler"; |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
@BeforeEach |
||||||
|
public void setup() { |
||||||
|
when(storageOperator.getStorageBaseDirectory()).thenReturn(BASE_DIRECTORY); |
||||||
|
loginUser = new User(); |
||||||
|
loginUser.setTenantId(1); |
||||||
|
LocaleContextHolder.setLocale(Locale.ENGLISH); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testValidate_skipLineNumInvalid() { |
||||||
|
FetchFileContentDto fetchFileContentDto = FetchFileContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.resourceFileAbsolutePath("/tmp") |
||||||
|
.skipLineNum(-1) |
||||||
|
.limit(-1) |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: skipLineNum must be greater than or equal to 0", |
||||||
|
() -> fetchFileContentDtoValidator.validate(fetchFileContentDto)); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testValidate_notUnderBaseDirectory() { |
||||||
|
FetchFileContentDto fetchFileContentDto = FetchFileContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.resourceFileAbsolutePath("/tmp") |
||||||
|
.skipLineNum(0) |
||||||
|
.limit(-1) |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: Invalidated resource path: /tmp", |
||||||
|
() -> fetchFileContentDtoValidator.validate(fetchFileContentDto)); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_filePathContainsIllegalSymbolic() { |
||||||
|
FetchFileContentDto fetchFileContentDto = FetchFileContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.resourceFileAbsolutePath("/tmp/dolphinscheduler/default/resources/..") |
||||||
|
.skipLineNum(0) |
||||||
|
.limit(-1) |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: Invalidated resource path: /tmp/dolphinscheduler/default/resources/..", |
||||||
|
() -> fetchFileContentDtoValidator.validate(fetchFileContentDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_IsNotFile() { |
||||||
|
FetchFileContentDto fetchFileContentDto = FetchFileContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.resourceFileAbsolutePath("/tmp/dolphinscheduler/default/resources/a") |
||||||
|
.skipLineNum(0) |
||||||
|
.limit(-1) |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The path is not a file: /tmp/dolphinscheduler/default/resources/a", |
||||||
|
() -> fetchFileContentDtoValidator.validate(fetchFileContentDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_fileNoPermission() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("test"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
FetchFileContentDto fetchFileContentDto = FetchFileContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.resourceFileAbsolutePath("/tmp/dolphinscheduler/default/resources/a.sql") |
||||||
|
.skipLineNum(0) |
||||||
|
.limit(-1) |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(fetchFileContentDto.getResourceFileAbsolutePath())).thenReturn(false); |
||||||
|
when(storageOperator.getResourceMetaData(fetchFileContentDto.getResourceFileAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(fetchFileContentDto.getResourceFileAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("a.sql") |
||||||
|
.isDirectory(false) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The user's tenant is test have no permission to access the resource: /tmp/dolphinscheduler/default/resources/a.sql", |
||||||
|
() -> fetchFileContentDtoValidator.validate(fetchFileContentDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void validate_fileExtensionInvalid() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("default"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
FetchFileContentDto fetchFileContentDto = FetchFileContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.resourceFileAbsolutePath("/tmp/dolphinscheduler/default/resources/a.jar") |
||||||
|
.skipLineNum(0) |
||||||
|
.limit(-1) |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(fetchFileContentDto.getResourceFileAbsolutePath())).thenReturn(false); |
||||||
|
when(storageOperator.getResourceMetaData(fetchFileContentDto.getResourceFileAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(fetchFileContentDto.getResourceFileAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("a.jar") |
||||||
|
.isDirectory(false) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The file type: jar cannot be fetched", |
||||||
|
() -> fetchFileContentDtoValidator.validate(fetchFileContentDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void validate() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("default"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
FetchFileContentDto fetchFileContentDto = FetchFileContentDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.resourceFileAbsolutePath("/tmp/dolphinscheduler/default/resources/a.sql") |
||||||
|
.skipLineNum(0) |
||||||
|
.limit(-1) |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(fetchFileContentDto.getResourceFileAbsolutePath())).thenReturn(false); |
||||||
|
when(storageOperator.getResourceMetaData(fetchFileContentDto.getResourceFileAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(fetchFileContentDto.getResourceFileAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("a.sql") |
||||||
|
.isDirectory(false) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
AssertionsHelper.assertDoesNotThrow(() -> fetchFileContentDtoValidator.validate(fetchFileContentDto)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,188 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import static org.apache.dolphinscheduler.api.AssertionsHelper.assertDoesNotThrow; |
||||||
|
import static org.apache.dolphinscheduler.api.AssertionsHelper.assertThrowServiceException; |
||||||
|
import static org.mockito.Mockito.when; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.RenameDirectoryDto; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.Tenant; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.ResourceMetadata; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import java.util.Locale; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.junit.jupiter.api.extension.ExtendWith; |
||||||
|
import org.mockito.InjectMocks; |
||||||
|
import org.mockito.Mock; |
||||||
|
import org.mockito.junit.jupiter.MockitoExtension; |
||||||
|
import org.springframework.context.i18n.LocaleContextHolder; |
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class) |
||||||
|
class RenameDirectoryDtoValidatorTest { |
||||||
|
|
||||||
|
@Mock |
||||||
|
private StorageOperator storageOperator; |
||||||
|
|
||||||
|
@Mock |
||||||
|
private TenantDao tenantDao; |
||||||
|
|
||||||
|
@InjectMocks |
||||||
|
private RenameDirectoryDtoValidator renameDirectoryDtoValidator; |
||||||
|
|
||||||
|
private static final String BASE_DIRECTORY = "/tmp/dolphinscheduler"; |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
@BeforeEach |
||||||
|
public void setup() { |
||||||
|
when(storageOperator.getStorageBaseDirectory()).thenReturn(BASE_DIRECTORY); |
||||||
|
loginUser = new User(); |
||||||
|
loginUser.setTenantId(1); |
||||||
|
LocaleContextHolder.setLocale(Locale.ENGLISH); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testValidate_notUnderBaseDirectory() { |
||||||
|
RenameDirectoryDto renameDirectoryDto = RenameDirectoryDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originDirectoryAbsolutePath("/tmp") |
||||||
|
.targetDirectoryAbsolutePath("/tmp1") |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: Invalidated resource path: /tmp", |
||||||
|
() -> renameDirectoryDtoValidator.validate(renameDirectoryDto)); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_directoryPathContainsIllegalSymbolic() { |
||||||
|
RenameDirectoryDto renameDirectoryDto = RenameDirectoryDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originDirectoryAbsolutePath("/tmp/dolphinscheduler/default/resources/..") |
||||||
|
.targetDirectoryAbsolutePath("/tmp/dolphinscheduler/default/resources/a") |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: Invalidated resource path: /tmp/dolphinscheduler/default/resources/..", |
||||||
|
() -> renameDirectoryDtoValidator.validate(renameDirectoryDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_originDirectoryNotExist() { |
||||||
|
RenameDirectoryDto renameDirectoryDto = RenameDirectoryDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originDirectoryAbsolutePath("/tmp/dolphinscheduler/default/resources/a") |
||||||
|
.targetDirectoryAbsolutePath("/tmp/dolphinscheduler/default/resources/b") |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: Thr resource is not exists: /tmp/dolphinscheduler/default/resources/a", |
||||||
|
() -> renameDirectoryDtoValidator.validate(renameDirectoryDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_originDirectoryNoPermission() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("test"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
RenameDirectoryDto renameDirectoryDto = RenameDirectoryDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originDirectoryAbsolutePath("/tmp/dolphinscheduler/default/resources/a") |
||||||
|
.targetDirectoryAbsolutePath("/tmp/dolphinscheduler/default/resources/b") |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(renameDirectoryDto.getOriginDirectoryAbsolutePath())).thenReturn(true); |
||||||
|
when(storageOperator.getResourceMetaData(renameDirectoryDto.getOriginDirectoryAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(renameDirectoryDto.getOriginDirectoryAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("a") |
||||||
|
.isDirectory(true) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The user's tenant is test have no permission to access the resource: /tmp/dolphinscheduler/default/resources/a", |
||||||
|
() -> renameDirectoryDtoValidator.validate(renameDirectoryDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_targetDirectoryAlreadyExist() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("default"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
RenameDirectoryDto renameDirectoryDto = RenameDirectoryDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originDirectoryAbsolutePath("/tmp/dolphinscheduler/default/resources/a") |
||||||
|
.targetDirectoryAbsolutePath("/tmp/dolphinscheduler/default/resources/b") |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(renameDirectoryDto.getOriginDirectoryAbsolutePath())).thenReturn(true); |
||||||
|
when(storageOperator.getResourceMetaData(renameDirectoryDto.getOriginDirectoryAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(renameDirectoryDto.getOriginDirectoryAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("a") |
||||||
|
.isDirectory(true) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
|
||||||
|
when(storageOperator.exists(renameDirectoryDto.getTargetDirectoryAbsolutePath())).thenReturn(true); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The resource is already exist: /tmp/dolphinscheduler/default/resources/b", |
||||||
|
() -> renameDirectoryDtoValidator.validate(renameDirectoryDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("default"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
RenameDirectoryDto renameDirectoryDto = RenameDirectoryDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originDirectoryAbsolutePath("/tmp/dolphinscheduler/default/resources/a") |
||||||
|
.targetDirectoryAbsolutePath("/tmp/dolphinscheduler/default/resources/b") |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(renameDirectoryDto.getOriginDirectoryAbsolutePath())).thenReturn(true); |
||||||
|
when(storageOperator.getResourceMetaData(renameDirectoryDto.getOriginDirectoryAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(renameDirectoryDto.getOriginDirectoryAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("a") |
||||||
|
.isDirectory(true) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
|
||||||
|
when(storageOperator.exists(renameDirectoryDto.getTargetDirectoryAbsolutePath())).thenReturn(false); |
||||||
|
when(storageOperator.getResourceMetaData(renameDirectoryDto.getTargetDirectoryAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(renameDirectoryDto.getOriginDirectoryAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("b") |
||||||
|
.isDirectory(true) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
|
||||||
|
assertDoesNotThrow(() -> renameDirectoryDtoValidator.validate(renameDirectoryDto)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,202 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.api.validator.resource; |
||||||
|
|
||||||
|
import static org.apache.dolphinscheduler.api.AssertionsHelper.assertThrowServiceException; |
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; |
||||||
|
import static org.mockito.Mockito.when; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.api.dto.resources.RenameFileDto; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.Tenant; |
||||||
|
import org.apache.dolphinscheduler.dao.entity.User; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.ResourceMetadata; |
||||||
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperator; |
||||||
|
|
||||||
|
import java.util.Locale; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.junit.jupiter.api.extension.ExtendWith; |
||||||
|
import org.mockito.InjectMocks; |
||||||
|
import org.mockito.Mock; |
||||||
|
import org.mockito.junit.jupiter.MockitoExtension; |
||||||
|
import org.springframework.context.i18n.LocaleContextHolder; |
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class) |
||||||
|
public class RenameFileDtoValidatorTest { |
||||||
|
|
||||||
|
@Mock |
||||||
|
private StorageOperator storageOperator; |
||||||
|
|
||||||
|
@Mock |
||||||
|
private TenantDao tenantDao; |
||||||
|
|
||||||
|
@InjectMocks |
||||||
|
private RenameFileDtoValidator renameFileDtoValidator; |
||||||
|
|
||||||
|
private static final String BASE_DIRECTORY = "/tmp/dolphinscheduler"; |
||||||
|
|
||||||
|
private User loginUser; |
||||||
|
|
||||||
|
@BeforeEach |
||||||
|
public void setup() { |
||||||
|
when(storageOperator.getStorageBaseDirectory()).thenReturn(BASE_DIRECTORY); |
||||||
|
loginUser = new User(); |
||||||
|
loginUser.setTenantId(1); |
||||||
|
LocaleContextHolder.setLocale(Locale.ENGLISH); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testValidate_notUnderBaseDirectory() { |
||||||
|
RenameFileDto renameFileDto = RenameFileDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originFileAbsolutePath("/tmp") |
||||||
|
.targetFileAbsolutePath("/tmp1") |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: Invalidated resource path: /tmp", |
||||||
|
() -> renameFileDtoValidator.validate(renameFileDto)); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_fileAbsolutePathContainsIllegalSymbolic() { |
||||||
|
RenameFileDto renameFileDto = RenameFileDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originFileAbsolutePath("/tmp/dolphinscheduler/default/resources/../a.txt") |
||||||
|
.targetFileAbsolutePath("/tmp/dolphinscheduler/default/resources/b.txt") |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: Invalidated resource path: /tmp/dolphinscheduler/default/resources/../a.txt", |
||||||
|
() -> renameFileDtoValidator.validate(renameFileDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_originFileNotExist() { |
||||||
|
RenameFileDto renameFileDto = RenameFileDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originFileAbsolutePath("/tmp/dolphinscheduler/default/resources/a.txt") |
||||||
|
.targetFileAbsolutePath("/tmp/dolphinscheduler/default/resources/b.txt") |
||||||
|
.build(); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: Thr resource is not exists: /tmp/dolphinscheduler/default/resources/a.txt", |
||||||
|
() -> renameFileDtoValidator.validate(renameFileDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_originFileIsNotFile() { |
||||||
|
RenameFileDto renameFileDto = RenameFileDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originFileAbsolutePath("/tmp/dolphinscheduler/default/resources/a") |
||||||
|
.targetFileAbsolutePath("/tmp/dolphinscheduler/default/resources/b.txt") |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(renameFileDto.getOriginFileAbsolutePath())).thenReturn(true); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The path is not a file: /tmp/dolphinscheduler/default/resources/a", |
||||||
|
() -> renameFileDtoValidator.validate(renameFileDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_originFileNoPermission() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("test"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
RenameFileDto renameFileDto = RenameFileDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originFileAbsolutePath("/tmp/dolphinscheduler/default/resources/a.txt") |
||||||
|
.targetFileAbsolutePath("/tmp/dolphinscheduler/default/resources/b.txt") |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(renameFileDto.getOriginFileAbsolutePath())).thenReturn(true); |
||||||
|
when(storageOperator.getResourceMetaData(renameFileDto.getOriginFileAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(renameFileDto.getOriginFileAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("a.txt") |
||||||
|
.isDirectory(false) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The user's tenant is test have no permission to access the resource: /tmp/dolphinscheduler/default/resources/a.txt", |
||||||
|
() -> renameFileDtoValidator.validate(renameFileDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate_targetFileAlreadyExist() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("default"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
RenameFileDto renameDirectoryDto = RenameFileDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originFileAbsolutePath("/tmp/dolphinscheduler/default/resources/a.txt") |
||||||
|
.targetFileAbsolutePath("/tmp/dolphinscheduler/default/resources/b.txt") |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(renameDirectoryDto.getOriginFileAbsolutePath())).thenReturn(true); |
||||||
|
when(storageOperator.getResourceMetaData(renameDirectoryDto.getOriginFileAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(renameDirectoryDto.getOriginFileAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("a.txt") |
||||||
|
.isDirectory(false) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
|
||||||
|
when(storageOperator.exists(renameDirectoryDto.getTargetFileAbsolutePath())).thenReturn(true); |
||||||
|
assertThrowServiceException( |
||||||
|
"Internal Server Error: The resource is already exist: /tmp/dolphinscheduler/default/resources/b.txt", |
||||||
|
() -> renameFileDtoValidator.validate(renameDirectoryDto)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testValidate() { |
||||||
|
Tenant tenant = new Tenant(); |
||||||
|
tenant.setTenantCode("default"); |
||||||
|
when(tenantDao.queryOptionalById(loginUser.getTenantId())).thenReturn(Optional.of(tenant)); |
||||||
|
|
||||||
|
RenameFileDto renameDirectoryDto = RenameFileDto.builder() |
||||||
|
.loginUser(loginUser) |
||||||
|
.originFileAbsolutePath("/tmp/dolphinscheduler/default/resources/a.txt") |
||||||
|
.targetFileAbsolutePath("/tmp/dolphinscheduler/default/resources/b.txt") |
||||||
|
.build(); |
||||||
|
when(storageOperator.exists(renameDirectoryDto.getOriginFileAbsolutePath())).thenReturn(true); |
||||||
|
when(storageOperator.getResourceMetaData(renameDirectoryDto.getOriginFileAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(renameDirectoryDto.getOriginFileAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("a.txt") |
||||||
|
.isDirectory(false) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
|
||||||
|
when(storageOperator.exists(renameDirectoryDto.getTargetFileAbsolutePath())).thenReturn(false); |
||||||
|
when(storageOperator.getResourceMetaData(renameDirectoryDto.getTargetFileAbsolutePath())) |
||||||
|
.thenReturn(ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(renameDirectoryDto.getTargetFileAbsolutePath()) |
||||||
|
.resourceBaseDirectory(BASE_DIRECTORY) |
||||||
|
.resourceRelativePath("b.txt") |
||||||
|
.isDirectory(false) |
||||||
|
.tenant("default") |
||||||
|
.build()); |
||||||
|
|
||||||
|
assertDoesNotThrow(() -> renameFileDtoValidator.validate(renameDirectoryDto)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.dao.repository; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.Tenant; |
||||||
|
|
||||||
|
public interface TenantDao extends IDao<Tenant> { |
||||||
|
|
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.dao.repository.impl; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.dao.entity.Tenant; |
||||||
|
import org.apache.dolphinscheduler.dao.mapper.TenantMapper; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.BaseDao; |
||||||
|
import org.apache.dolphinscheduler.dao.repository.TenantDao; |
||||||
|
|
||||||
|
import lombok.NonNull; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Repository; |
||||||
|
|
||||||
|
@Repository |
||||||
|
public class TenantDaoImpl extends BaseDao<Tenant, TenantMapper> implements TenantDao { |
||||||
|
|
||||||
|
public TenantDaoImpl(@NonNull TenantMapper tenantMapper) { |
||||||
|
super(tenantMapper); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.plugin.storage.abs; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class AbsStorageProperties { |
||||||
|
|
||||||
|
private String containerName; |
||||||
|
private String connectionString; |
||||||
|
private String storageAccountName; |
||||||
|
private String resourceUploadPath; |
||||||
|
|
||||||
|
} |
@ -1,274 +0,0 @@ |
|||||||
/* |
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
* contributor license agreements. See the NOTICE file distributed with |
|
||||||
* this work for additional information regarding copyright ownership. |
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
* (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.plugin.storage.abs; |
|
||||||
|
|
||||||
import static org.apache.dolphinscheduler.common.constants.Constants.FOLDER_SEPARATOR; |
|
||||||
import static org.apache.dolphinscheduler.common.constants.Constants.FORMAT_S_S; |
|
||||||
import static org.mockito.ArgumentMatchers.anyString; |
|
||||||
import static org.mockito.Mockito.doNothing; |
|
||||||
import static org.mockito.Mockito.doReturn; |
|
||||||
import static org.mockito.Mockito.times; |
|
||||||
import static org.mockito.Mockito.verify; |
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.plugin.storage.api.StorageEntity; |
|
||||||
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.util.Collections; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions; |
|
||||||
import org.junit.jupiter.api.BeforeEach; |
|
||||||
import org.junit.jupiter.api.Test; |
|
||||||
import org.junit.jupiter.api.extension.ExtendWith; |
|
||||||
import org.mockito.Mock; |
|
||||||
import org.mockito.Mockito; |
|
||||||
import org.mockito.junit.jupiter.MockitoExtension; |
|
||||||
|
|
||||||
import com.azure.storage.blob.BlobClient; |
|
||||||
import com.azure.storage.blob.BlobContainerClient; |
|
||||||
import com.azure.storage.blob.BlobServiceClient; |
|
||||||
import com.azure.storage.blob.specialized.BlockBlobClient; |
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class) |
|
||||||
public class AbsStorageOperatorTest { |
|
||||||
|
|
||||||
private static final String CONNECTION_STRING_MOCK = "CONNECTION_STRING_MOCK"; |
|
||||||
|
|
||||||
private static final String ACCOUNT_NAME_MOCK = "ACCOUNT_NAME_MOCK"; |
|
||||||
|
|
||||||
private static final String CONTAINER_NAME_MOCK = "CONTAINER_NAME_MOCK"; |
|
||||||
|
|
||||||
private static final String TENANT_CODE_MOCK = "TENANT_CODE_MOCK"; |
|
||||||
|
|
||||||
private static final String DIR_MOCK = "DIR_MOCK"; |
|
||||||
|
|
||||||
private static final String FILE_NAME_MOCK = "FILE_NAME_MOCK"; |
|
||||||
|
|
||||||
private static final String FILE_PATH_MOCK = "FILE_PATH_MOCK"; |
|
||||||
|
|
||||||
private static final String FULL_NAME = "/tmp/dir1/"; |
|
||||||
|
|
||||||
private static final String DEFAULT_PATH = "/tmp/"; |
|
||||||
|
|
||||||
@Mock |
|
||||||
private BlobContainerClient blobContainerClient; |
|
||||||
|
|
||||||
@Mock |
|
||||||
private BlobServiceClient blobServiceClient; |
|
||||||
|
|
||||||
@Mock |
|
||||||
private BlockBlobClient blockBlobClient; |
|
||||||
|
|
||||||
@Mock |
|
||||||
private BlobClient blobClient; |
|
||||||
|
|
||||||
private AbsStorageOperator absStorageOperator; |
|
||||||
|
|
||||||
@BeforeEach |
|
||||||
public void setUp() throws Exception { |
|
||||||
absStorageOperator = Mockito.spy(AbsStorageOperator.class); |
|
||||||
Mockito.doReturn(CONNECTION_STRING_MOCK).when(absStorageOperator).readConnectionString(); |
|
||||||
Mockito.doReturn(CONTAINER_NAME_MOCK).when(absStorageOperator).readContainerName(); |
|
||||||
Mockito.doReturn(ACCOUNT_NAME_MOCK).when(absStorageOperator).readAccountName(); |
|
||||||
Mockito.doReturn(blobContainerClient).when(absStorageOperator).buildBlobContainerClient(); |
|
||||||
Mockito.doReturn(blobServiceClient).when(absStorageOperator).buildBlobServiceClient(); |
|
||||||
Mockito.doNothing().when(absStorageOperator).checkContainerNameExists(); |
|
||||||
|
|
||||||
absStorageOperator.init(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testInit() throws Exception { |
|
||||||
verify(absStorageOperator, times(1)).buildBlobServiceClient(); |
|
||||||
verify(absStorageOperator, times(1)).buildBlobContainerClient(); |
|
||||||
Assertions.assertEquals(CONNECTION_STRING_MOCK, absStorageOperator.getConnectionString()); |
|
||||||
Assertions.assertEquals(CONTAINER_NAME_MOCK, absStorageOperator.getContainerName()); |
|
||||||
Assertions.assertEquals(ACCOUNT_NAME_MOCK, absStorageOperator.getStorageAccountName()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void createTenantResAndUdfDir() throws Exception { |
|
||||||
doReturn(DIR_MOCK).when(absStorageOperator).getAbsResDir(TENANT_CODE_MOCK); |
|
||||||
doReturn(DIR_MOCK).when(absStorageOperator).getAbsUdfDir(TENANT_CODE_MOCK); |
|
||||||
doReturn(true).when(absStorageOperator).mkdir(TENANT_CODE_MOCK, DIR_MOCK); |
|
||||||
absStorageOperator.createTenantDirIfNotExists(TENANT_CODE_MOCK); |
|
||||||
verify(absStorageOperator, times(2)).mkdir(TENANT_CODE_MOCK, DIR_MOCK); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getResDir() { |
|
||||||
final String expectedResourceDir = String.format("dolphinscheduler/%s/resources/", TENANT_CODE_MOCK); |
|
||||||
final String dir = absStorageOperator.getResDir(TENANT_CODE_MOCK); |
|
||||||
Assertions.assertEquals(expectedResourceDir, dir); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getUdfDir() { |
|
||||||
final String expectedUdfDir = String.format("dolphinscheduler/%s/udfs/", TENANT_CODE_MOCK); |
|
||||||
final String dir = absStorageOperator.getUdfDir(TENANT_CODE_MOCK); |
|
||||||
Assertions.assertEquals(expectedUdfDir, dir); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void mkdirWhenDirExists() { |
|
||||||
boolean isSuccess = false; |
|
||||||
try { |
|
||||||
final String key = DIR_MOCK + FOLDER_SEPARATOR; |
|
||||||
Mockito.doReturn(true).when(absStorageOperator).isObjectExists(key); |
|
||||||
isSuccess = absStorageOperator.mkdir(TENANT_CODE_MOCK, DIR_MOCK); |
|
||||||
|
|
||||||
} catch (IOException e) { |
|
||||||
Assertions.fail("test failed due to unexpected IO exception"); |
|
||||||
} |
|
||||||
|
|
||||||
Assertions.assertTrue(isSuccess); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getResourceFullName() { |
|
||||||
final String expectedResourceFileName = |
|
||||||
String.format("dolphinscheduler/%s/resources/%s", TENANT_CODE_MOCK, FILE_NAME_MOCK); |
|
||||||
final String resourceFileName = absStorageOperator.getResourceFullName(TENANT_CODE_MOCK, FILE_NAME_MOCK); |
|
||||||
Assertions.assertEquals(expectedResourceFileName, resourceFileName); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getFileName() { |
|
||||||
final String expectedFileName = |
|
||||||
String.format("dolphinscheduler/%s/resources/%s", TENANT_CODE_MOCK, FILE_NAME_MOCK); |
|
||||||
final String fileName = absStorageOperator.getFileName(ResourceType.FILE, TENANT_CODE_MOCK, FILE_NAME_MOCK); |
|
||||||
Assertions.assertEquals(expectedFileName, fileName); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void exists() { |
|
||||||
boolean doesExist = false; |
|
||||||
doReturn(true).when(absStorageOperator).isObjectExists(FILE_NAME_MOCK); |
|
||||||
try { |
|
||||||
doesExist = absStorageOperator.exists(FILE_NAME_MOCK); |
|
||||||
} catch (IOException e) { |
|
||||||
Assertions.fail("unexpected IO exception in unit test"); |
|
||||||
} |
|
||||||
|
|
||||||
Assertions.assertTrue(doesExist); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void delete() { |
|
||||||
boolean isDeleted = false; |
|
||||||
doReturn(true).when(absStorageOperator).isObjectExists(FILE_NAME_MOCK); |
|
||||||
Mockito.doReturn(blobClient).when(blobContainerClient).getBlobClient(Mockito.anyString()); |
|
||||||
try { |
|
||||||
isDeleted = absStorageOperator.delete(FILE_NAME_MOCK, true); |
|
||||||
} catch (IOException e) { |
|
||||||
Assertions.fail("unexpected IO exception in unit test"); |
|
||||||
} |
|
||||||
|
|
||||||
Assertions.assertTrue(isDeleted); |
|
||||||
verify(blobClient, times(1)).delete(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void copy() { |
|
||||||
boolean isSuccess = false; |
|
||||||
Mockito.doReturn(blobClient).when(blobContainerClient).getBlobClient(Mockito.anyString()); |
|
||||||
Mockito.doReturn(blockBlobClient).when(blobClient).getBlockBlobClient(); |
|
||||||
try { |
|
||||||
isSuccess = absStorageOperator.copy(FILE_PATH_MOCK, FILE_PATH_MOCK, false, false); |
|
||||||
} catch (IOException e) { |
|
||||||
Assertions.fail("unexpected IO exception in unit test"); |
|
||||||
} |
|
||||||
|
|
||||||
Assertions.assertTrue(isSuccess); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void deleteTenant() { |
|
||||||
doNothing().when(absStorageOperator).deleteTenantCode(anyString()); |
|
||||||
try { |
|
||||||
absStorageOperator.deleteTenant(TENANT_CODE_MOCK); |
|
||||||
} catch (Exception e) { |
|
||||||
Assertions.fail("unexpected exception caught in unit test"); |
|
||||||
} |
|
||||||
|
|
||||||
verify(absStorageOperator, times(1)).deleteTenantCode(anyString()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getGcsResDir() { |
|
||||||
final String expectedGcsResDir = String.format("dolphinscheduler/%s/resources", TENANT_CODE_MOCK); |
|
||||||
final String gcsResDir = absStorageOperator.getAbsResDir(TENANT_CODE_MOCK); |
|
||||||
Assertions.assertEquals(expectedGcsResDir, gcsResDir); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getGcsUdfDir() { |
|
||||||
final String expectedGcsUdfDir = String.format("dolphinscheduler/%s/udfs", TENANT_CODE_MOCK); |
|
||||||
final String gcsUdfDir = absStorageOperator.getAbsUdfDir(TENANT_CODE_MOCK); |
|
||||||
Assertions.assertEquals(expectedGcsUdfDir, gcsUdfDir); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getGcsTenantDir() { |
|
||||||
final String expectedGcsTenantDir = String.format(FORMAT_S_S, DIR_MOCK, TENANT_CODE_MOCK); |
|
||||||
doReturn(DIR_MOCK).when(absStorageOperator).getGcsDataBasePath(); |
|
||||||
final String gcsTenantDir = absStorageOperator.getAbsTenantDir(TENANT_CODE_MOCK); |
|
||||||
Assertions.assertEquals(expectedGcsTenantDir, gcsTenantDir); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void deleteDir() { |
|
||||||
Mockito.doReturn(blobClient).when(blobContainerClient).getBlobClient(Mockito.anyString()); |
|
||||||
doReturn(true).when(absStorageOperator).isObjectExists(Mockito.any()); |
|
||||||
absStorageOperator.deleteDirectory(DIR_MOCK); |
|
||||||
verify(blobClient, times(1)).delete(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testGetFileStatus() throws Exception { |
|
||||||
StorageEntity entity = |
|
||||||
absStorageOperator.getFileStatus(FULL_NAME, DEFAULT_PATH, TENANT_CODE_MOCK, ResourceType.FILE); |
|
||||||
Assertions.assertEquals(FULL_NAME, entity.getFullName()); |
|
||||||
Assertions.assertEquals("dir1/", entity.getFileName()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testListFilesStatus() throws Exception { |
|
||||||
Mockito.doReturn(null).when(blobContainerClient).listBlobsByHierarchy(Mockito.any()); |
|
||||||
List<StorageEntity> result = |
|
||||||
absStorageOperator.listFilesStatus(FULL_NAME, DEFAULT_PATH, TENANT_CODE_MOCK, ResourceType.FILE); |
|
||||||
verify(blobContainerClient, times(1)).listBlobsByHierarchy(Mockito.any()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testListFilesStatusRecursively() throws Exception { |
|
||||||
StorageEntity entity = new StorageEntity(); |
|
||||||
entity.setFullName(FULL_NAME); |
|
||||||
|
|
||||||
doReturn(entity).when(absStorageOperator).getFileStatus(FULL_NAME, DEFAULT_PATH, TENANT_CODE_MOCK, |
|
||||||
ResourceType.FILE); |
|
||||||
doReturn(Collections.EMPTY_LIST).when(absStorageOperator).listFilesStatus(anyString(), anyString(), anyString(), |
|
||||||
Mockito.any(ResourceType.class)); |
|
||||||
|
|
||||||
List<StorageEntity> result = |
|
||||||
absStorageOperator.listFilesStatusRecursively(FULL_NAME, DEFAULT_PATH, TENANT_CODE_MOCK, |
|
||||||
ResourceType.FILE); |
|
||||||
Assertions.assertEquals(0, result.size()); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,110 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.plugin.storage.api; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.common.constants.Constants; |
||||||
|
import org.apache.dolphinscheduler.common.utils.FileUtils; |
||||||
|
import org.apache.dolphinscheduler.common.utils.PropertyUtils; |
||||||
|
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
|
||||||
|
import com.google.common.base.Preconditions; |
||||||
|
import com.google.common.io.Files; |
||||||
|
|
||||||
|
public abstract class AbstractStorageOperator implements StorageOperator { |
||||||
|
|
||||||
|
protected final String resourceBaseAbsolutePath; |
||||||
|
|
||||||
|
public AbstractStorageOperator(String resourceBaseAbsolutePath) { |
||||||
|
Preconditions.checkNotNull(resourceBaseAbsolutePath, "Resource upload path should not be null"); |
||||||
|
this.resourceBaseAbsolutePath = resourceBaseAbsolutePath; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ResourceMetadata getResourceMetaData(String resourceAbsolutePath) { |
||||||
|
String storageBaseDirectory = getStorageBaseDirectory(); |
||||||
|
String resourceSegment = StringUtils.substringAfter(resourceAbsolutePath, storageBaseDirectory); |
||||||
|
String[] segments = StringUtils.split(resourceSegment, File.separator, 3); |
||||||
|
if (segments.length == 0) { |
||||||
|
throw new IllegalArgumentException("Invalid resource path: " + resourceAbsolutePath); |
||||||
|
} |
||||||
|
return ResourceMetadata.builder() |
||||||
|
.resourceAbsolutePath(resourceAbsolutePath) |
||||||
|
.resourceBaseDirectory(storageBaseDirectory) |
||||||
|
.isDirectory(Files.getFileExtension(resourceAbsolutePath).isEmpty()) |
||||||
|
.tenant(segments[0]) |
||||||
|
.resourceType(segments[1].equals(FILE_FOLDER_NAME) ? ResourceType.FILE : ResourceType.UDF) |
||||||
|
.resourceRelativePath(segments.length == 2 ? "/" : segments[2]) |
||||||
|
.resourceParentAbsolutePath(StringUtils.substringBeforeLast(resourceAbsolutePath, File.separator)) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getStorageBaseDirectory() { |
||||||
|
// All directory should end with File.separator
|
||||||
|
return PropertyUtils.getString(Constants.RESOURCE_UPLOAD_PATH, "/dolphinscheduler"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getStorageBaseDirectory(String tenantCode) { |
||||||
|
if (StringUtils.isEmpty(tenantCode)) { |
||||||
|
throw new IllegalArgumentException("Tenant code should not be empty"); |
||||||
|
} |
||||||
|
// All directory should end with File.separator
|
||||||
|
return FileUtils.concatFilePath(getStorageBaseDirectory(), tenantCode); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getStorageBaseDirectory(String tenantCode, ResourceType resourceType) { |
||||||
|
String tenantBaseDirectory = getStorageBaseDirectory(tenantCode); |
||||||
|
if (resourceType == null) { |
||||||
|
throw new IllegalArgumentException("Resource type should not be null"); |
||||||
|
} |
||||||
|
String resourceBaseDirectory; |
||||||
|
switch (resourceType) { |
||||||
|
case FILE: |
||||||
|
resourceBaseDirectory = FileUtils.concatFilePath(tenantBaseDirectory, FILE_FOLDER_NAME); |
||||||
|
break; |
||||||
|
case UDF: |
||||||
|
resourceBaseDirectory = FileUtils.concatFilePath(tenantBaseDirectory, UDF_FOLDER_NAME); |
||||||
|
break; |
||||||
|
case ALL: |
||||||
|
resourceBaseDirectory = tenantBaseDirectory; |
||||||
|
break; |
||||||
|
default: |
||||||
|
throw new IllegalArgumentException("Resource type: " + resourceType + " not supported"); |
||||||
|
} |
||||||
|
// All directory should end with File.separator
|
||||||
|
return resourceBaseDirectory; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getStorageFileAbsolutePath(String tenantCode, String fileName) { |
||||||
|
return FileUtils.concatFilePath(getStorageBaseDirectory(tenantCode, ResourceType.FILE), fileName); |
||||||
|
} |
||||||
|
|
||||||
|
protected void exceptionIfPathEmpty(String resourceAbsolutePath) { |
||||||
|
if (StringUtils.isEmpty(resourceAbsolutePath)) { |
||||||
|
throw new IllegalArgumentException("Resource path should not be empty"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.plugin.storage.api; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class ResourceMetadata { |
||||||
|
|
||||||
|
private String resourceAbsolutePath; |
||||||
|
|
||||||
|
private String resourceBaseDirectory; |
||||||
|
private String tenant; |
||||||
|
private ResourceType resourceType; |
||||||
|
private String resourceRelativePath; |
||||||
|
private String resourceParentAbsolutePath; |
||||||
|
private boolean isDirectory; |
||||||
|
|
||||||
|
} |
@ -1,203 +0,0 @@ |
|||||||
/* |
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
* contributor license agreements. See the NOTICE file distributed with |
|
||||||
* this work for additional information regarding copyright ownership. |
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
* (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.plugin.storage.api; |
|
||||||
|
|
||||||
import static org.apache.dolphinscheduler.common.constants.Constants.RESOURCE_TYPE_FILE; |
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.common.constants.Constants; |
|
||||||
import org.apache.dolphinscheduler.common.enums.ResUploadType; |
|
||||||
import org.apache.dolphinscheduler.common.utils.PropertyUtils; |
|
||||||
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
public interface StorageOperate { |
|
||||||
|
|
||||||
String RESOURCE_UPLOAD_PATH = PropertyUtils.getString(Constants.RESOURCE_UPLOAD_PATH, "/dolphinscheduler"); |
|
||||||
|
|
||||||
/** |
|
||||||
* if the resource of tenant 's exist, the resource of folder will be created |
|
||||||
* @param tenantCode |
|
||||||
* @throws Exception |
|
||||||
*/ |
|
||||||
void createTenantDirIfNotExists(String tenantCode) throws Exception; |
|
||||||
|
|
||||||
/** |
|
||||||
* get the resource directory of tenant |
|
||||||
* @param tenantCode |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
String getResDir(String tenantCode); |
|
||||||
|
|
||||||
/** |
|
||||||
* return the udf directory of tenant |
|
||||||
* @param tenantCode |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
String getUdfDir(String tenantCode); |
|
||||||
|
|
||||||
/** |
|
||||||
* create the directory that the path of tenant wanted to create |
|
||||||
* @param tenantCode |
|
||||||
* @param path |
|
||||||
* @return |
|
||||||
* @throws IOException |
|
||||||
*/ |
|
||||||
boolean mkdir(String tenantCode, String path) throws IOException; |
|
||||||
|
|
||||||
/** |
|
||||||
* get the path of the resource file (fullName) |
|
||||||
* @param tenantCode |
|
||||||
* @param fileName |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
String getResourceFullName(String tenantCode, String fileName); |
|
||||||
|
|
||||||
/** |
|
||||||
* get the path of the resource file excluding the base path (fileName) |
|
||||||
*/ |
|
||||||
default String getResourceFileName(String tenantCode, String fullName) { |
|
||||||
String resDir = getResDir(tenantCode); |
|
||||||
String filenameReplaceResDir = fullName.replaceFirst(resDir, ""); |
|
||||||
if (!filenameReplaceResDir.equals(fullName)) { |
|
||||||
return filenameReplaceResDir; |
|
||||||
} |
|
||||||
|
|
||||||
// Replace resource dir not effective in case of run workflow with different tenant from resource file's.
|
|
||||||
// this is backup solution to get related path, by split with RESOURCE_TYPE_FILE
|
|
||||||
return filenameReplaceResDir.contains(RESOURCE_TYPE_FILE) |
|
||||||
? filenameReplaceResDir.split(String.format("%s/", RESOURCE_TYPE_FILE))[1] |
|
||||||
: filenameReplaceResDir; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* get the path of the file |
|
||||||
* @param resourceType |
|
||||||
* @param tenantCode |
|
||||||
* @param fileName |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
String getFileName(ResourceType resourceType, String tenantCode, String fileName); |
|
||||||
|
|
||||||
/** |
|
||||||
* predicate if the resource of tenant exists |
|
||||||
* @param fullName |
|
||||||
* @return |
|
||||||
* @throws IOException |
|
||||||
*/ |
|
||||||
boolean exists(String fullName) throws IOException; |
|
||||||
|
|
||||||
/** |
|
||||||
* delete the resource of filePath |
|
||||||
* todo if the filePath is the type of directory ,the files in the filePath need to be deleted at all |
|
||||||
* @param filePath |
|
||||||
* @param recursive |
|
||||||
* @return |
|
||||||
* @throws IOException |
|
||||||
*/ |
|
||||||
boolean delete(String filePath, boolean recursive) throws IOException; |
|
||||||
|
|
||||||
boolean delete(String filePath, List<String> childrenPathArray, boolean recursive) throws IOException; |
|
||||||
|
|
||||||
/** |
|
||||||
* copy the file from srcPath to dstPath |
|
||||||
* @param srcPath |
|
||||||
* @param dstPath |
|
||||||
* @param deleteSource if need to delete the file of srcPath |
|
||||||
* @param overwrite |
|
||||||
* @return |
|
||||||
* @throws IOException |
|
||||||
*/ |
|
||||||
boolean copy(String srcPath, String dstPath, boolean deleteSource, boolean overwrite) throws IOException; |
|
||||||
|
|
||||||
/** |
|
||||||
* get the root path of the tenant with resourceType |
|
||||||
* @param resourceType |
|
||||||
* @param tenantCode |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
String getDir(ResourceType resourceType, String tenantCode); |
|
||||||
|
|
||||||
/** |
|
||||||
* upload the local srcFile to dstPath |
|
||||||
* @param tenantCode |
|
||||||
* @param srcFile |
|
||||||
* @param dstPath |
|
||||||
* @param deleteSource |
|
||||||
* @param overwrite |
|
||||||
* @return |
|
||||||
* @throws IOException |
|
||||||
*/ |
|
||||||
boolean upload(String tenantCode, String srcFile, String dstPath, boolean deleteSource, |
|
||||||
boolean overwrite) throws IOException; |
|
||||||
|
|
||||||
/** |
|
||||||
* download the srcPath to local |
|
||||||
* |
|
||||||
* @param srcFilePath the full path of the srcPath |
|
||||||
* @param dstFile |
|
||||||
* @param overwrite |
|
||||||
* @throws IOException |
|
||||||
*/ |
|
||||||
void download(String srcFilePath, String dstFile, boolean overwrite) throws IOException; |
|
||||||
|
|
||||||
/** |
|
||||||
* vim the context of filePath |
|
||||||
* @param tenantCode |
|
||||||
* @param filePath |
|
||||||
* @param skipLineNums |
|
||||||
* @param limit |
|
||||||
* @return |
|
||||||
* @throws IOException |
|
||||||
*/ |
|
||||||
List<String> vimFile(String tenantCode, String filePath, int skipLineNums, int limit) throws IOException; |
|
||||||
|
|
||||||
/** |
|
||||||
* delete the files and directory of the tenant |
|
||||||
* |
|
||||||
* @param tenantCode |
|
||||||
* @throws Exception |
|
||||||
*/ |
|
||||||
void deleteTenant(String tenantCode) throws Exception; |
|
||||||
|
|
||||||
/** |
|
||||||
* return the storageType |
|
||||||
* |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
ResUploadType returnStorageType(); |
|
||||||
|
|
||||||
/** |
|
||||||
* return files and folders in the current directory and subdirectories |
|
||||||
* */ |
|
||||||
List<StorageEntity> listFilesStatusRecursively(String path, String defaultPath, String tenantCode, |
|
||||||
ResourceType type); |
|
||||||
|
|
||||||
/** |
|
||||||
* return files and folders in the current directory |
|
||||||
* */ |
|
||||||
List<StorageEntity> listFilesStatus(String path, String defaultPath, String tenantCode, |
|
||||||
ResourceType type) throws Exception; |
|
||||||
|
|
||||||
/** |
|
||||||
* return a file status |
|
||||||
* */ |
|
||||||
StorageEntity getFileStatus(String path, String defaultPath, String tenantCode, |
|
||||||
ResourceType type) throws Exception; |
|
||||||
} |
|
@ -0,0 +1,157 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.plugin.storage.api; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
||||||
|
|
||||||
|
import java.nio.file.FileAlreadyExistsException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public interface StorageOperator { |
||||||
|
|
||||||
|
String FILE_FOLDER_NAME = "resources"; |
||||||
|
String UDF_FOLDER_NAME = "udfs"; |
||||||
|
|
||||||
|
ResourceMetadata getResourceMetaData(String resourceAbsolutePath); |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the absolute path of base directory. |
||||||
|
* |
||||||
|
* @return the base directory. e.g. file:///tmp/dolphinscheduler/, /tmp/dolphinscheduler/
|
||||||
|
*/ |
||||||
|
String getStorageBaseDirectory(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the absolute path of directory which will be used by the given tenant. the tenant directory is under the base directory. |
||||||
|
* |
||||||
|
* @param tenantCode the tenant code, cannot be empty |
||||||
|
* @return the tenant directory. e.g. file:///tmp/dolphinscheduler/default/
|
||||||
|
*/ |
||||||
|
String getStorageBaseDirectory(String tenantCode); |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the absolute path of directory which will be used by the given tenant and resource type. the resource directory is under the tenant directory. |
||||||
|
* <p> If the resource type is FILE, will be 'file:///tmp/dolphinscheduler/default/resources/'.
|
||||||
|
* <p> If the resource type is UDF, will be 'is file:///tmp/dolphinscheduler/default/udfs/'.
|
||||||
|
* <p> If the resource type is ALL, will be 'is file:///tmp/dolphinscheduler/default/'.
|
||||||
|
* |
||||||
|
* @param tenantCode the tenant code, cannot be empty |
||||||
|
* @param resourceType the resource type, cannot be null |
||||||
|
* @return the resource directory. e.g. file:///tmp/dolphinscheduler/default/resources/
|
||||||
|
*/ |
||||||
|
String getStorageBaseDirectory(String tenantCode, ResourceType resourceType); |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the absolute path of the file in the storage. the file will under the file resource directory. |
||||||
|
* |
||||||
|
* @param tenantCode the tenant code, cannot be empty |
||||||
|
* @param fileName the file name, cannot be empty |
||||||
|
* @return the file absolute path. e.g. file:///tmp/dolphinscheduler/default/resources/test.sh
|
||||||
|
*/ |
||||||
|
String getStorageFileAbsolutePath(String tenantCode, String fileName); |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a directory if the directory is already exists will throw exception(Dependent on the storage implementation). |
||||||
|
* <p> If the directory is not exists, will create the directory. |
||||||
|
* <p> If the parent directory is not exists, will create the parent directory. |
||||||
|
* <p> If the directory is already exists, will throw {@link FileAlreadyExistsException}. |
||||||
|
* |
||||||
|
* @param directoryAbsolutePath the directory absolute path |
||||||
|
*/ |
||||||
|
void createStorageDir(String directoryAbsolutePath); |
||||||
|
|
||||||
|
/** |
||||||
|
* Check if the resource exists. |
||||||
|
* |
||||||
|
* @param resourceAbsolutePath the resource absolute path |
||||||
|
* @return true if the resource exists, otherwise false |
||||||
|
*/ |
||||||
|
boolean exists(String resourceAbsolutePath); |
||||||
|
|
||||||
|
/** |
||||||
|
* Delete the resource, if the resourceAbsolutePath is not exists, will do nothing. |
||||||
|
* |
||||||
|
* @param resourceAbsolutePath the resource absolute path |
||||||
|
* @param recursive whether to delete all the sub file/directory under the given resource |
||||||
|
*/ |
||||||
|
void delete(String resourceAbsolutePath, boolean recursive); |
||||||
|
|
||||||
|
/** |
||||||
|
* Copy the resource from the source path to the destination path. |
||||||
|
* |
||||||
|
* @param srcAbsolutePath the source path |
||||||
|
* @param dstAbsolutePath the destination path |
||||||
|
* @param deleteSource whether to delete the source path after copying |
||||||
|
* @param overwrite whether to overwrite the destination path if it exists |
||||||
|
*/ |
||||||
|
void copy(String srcAbsolutePath, String dstAbsolutePath, boolean deleteSource, boolean overwrite); |
||||||
|
|
||||||
|
/** |
||||||
|
* Move the resource from the source path to the destination path. |
||||||
|
* |
||||||
|
* @param srcLocalFileAbsolutePath the source local file |
||||||
|
* @param dstAbsolutePath the destination path |
||||||
|
* @param deleteSource whether to delete the source path after moving |
||||||
|
* @param overwrite whether to overwrite the destination path if it exists |
||||||
|
*/ |
||||||
|
void upload(String srcLocalFileAbsolutePath, String dstAbsolutePath, boolean deleteSource, boolean overwrite); |
||||||
|
|
||||||
|
/** |
||||||
|
* Download the resource from the source path to the destination path. |
||||||
|
* |
||||||
|
* @param srcFileAbsolutePath the source path |
||||||
|
* @param dstAbsoluteFile the destination file |
||||||
|
* @param overwrite whether to overwrite the destination file if it exists |
||||||
|
*/ |
||||||
|
void download(String srcFileAbsolutePath, String dstAbsoluteFile, boolean overwrite); |
||||||
|
|
||||||
|
/** |
||||||
|
* Fetch the content of the file. |
||||||
|
* |
||||||
|
* @param fileAbsolutePath the file path |
||||||
|
* @param skipLineNums the number of lines to skip |
||||||
|
* @param limit the number of lines to read |
||||||
|
* @return the content of the file |
||||||
|
*/ |
||||||
|
List<String> fetchFileContent(String fileAbsolutePath, int skipLineNums, int limit); |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the {@link StorageEntity} under the given path. |
||||||
|
* <p>If the path is a file, return the file status. |
||||||
|
* <p>If the path is a directory, return the file/directory under the directory. |
||||||
|
* <p>If the path is not exist, will return empty. |
||||||
|
* |
||||||
|
* @param resourceAbsolutePath the resource absolute path, cannot be empty |
||||||
|
*/ |
||||||
|
List<StorageEntity> listStorageEntity(String resourceAbsolutePath); |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the {@link StorageEntity} which is file under the given path |
||||||
|
* |
||||||
|
* @param resourceAbsolutePath the resource absolute path, cannot be empty |
||||||
|
*/ |
||||||
|
List<StorageEntity> listFileStorageEntityRecursively(String resourceAbsolutePath); |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the {@link StorageEntity} under the current directory |
||||||
|
* |
||||||
|
* @param resourceAbsolutePath the resource absolute path, cannot be empty |
||||||
|
*/ |
||||||
|
StorageEntity getStorageEntity(String resourceAbsolutePath); |
||||||
|
|
||||||
|
} |
4
dolphinscheduler-storage-plugin/dolphinscheduler-storage-api/src/main/java/org/apache/dolphinscheduler/plugin/storage/api/StorageOperateFactory.java → dolphinscheduler-storage-plugin/dolphinscheduler-storage-api/src/main/java/org/apache/dolphinscheduler/plugin/storage/api/StorageOperatorFactory.java
4
dolphinscheduler-storage-plugin/dolphinscheduler-storage-api/src/main/java/org/apache/dolphinscheduler/plugin/storage/api/StorageOperateFactory.java → dolphinscheduler-storage-plugin/dolphinscheduler-storage-api/src/main/java/org/apache/dolphinscheduler/plugin/storage/api/StorageOperatorFactory.java
@ -0,0 +1,36 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.plugin.storage.gcs; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class GcsStorageProperties { |
||||||
|
|
||||||
|
private String bucketName; |
||||||
|
|
||||||
|
private String credential; |
||||||
|
|
||||||
|
private String resourceUploadPath; |
||||||
|
} |
@ -1,290 +0,0 @@ |
|||||||
/* |
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
* contributor license agreements. See the NOTICE file distributed with |
|
||||||
* this work for additional information regarding copyright ownership. |
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
* (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.plugin.storage.gcs; |
|
||||||
|
|
||||||
import static org.apache.dolphinscheduler.common.constants.Constants.FOLDER_SEPARATOR; |
|
||||||
import static org.apache.dolphinscheduler.common.constants.Constants.FORMAT_S_S; |
|
||||||
import static org.mockito.ArgumentMatchers.anyString; |
|
||||||
import static org.mockito.Mockito.doNothing; |
|
||||||
import static org.mockito.Mockito.doReturn; |
|
||||||
import static org.mockito.Mockito.times; |
|
||||||
import static org.mockito.Mockito.verify; |
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.plugin.storage.api.StorageEntity; |
|
||||||
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.util.Collections; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions; |
|
||||||
import org.junit.jupiter.api.BeforeEach; |
|
||||||
import org.junit.jupiter.api.Test; |
|
||||||
import org.junit.jupiter.api.extension.ExtendWith; |
|
||||||
import org.mockito.Mock; |
|
||||||
import org.mockito.Mockito; |
|
||||||
import org.mockito.junit.jupiter.MockitoExtension; |
|
||||||
|
|
||||||
import com.google.cloud.storage.BlobId; |
|
||||||
import com.google.cloud.storage.BlobInfo; |
|
||||||
import com.google.cloud.storage.Storage; |
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class) |
|
||||||
public class GcsStorageOperatorTest { |
|
||||||
|
|
||||||
private static final String CREDENTIAL_MOCK = "CREDENTIAL_MOCK"; |
|
||||||
|
|
||||||
private static final String BUCKET_NAME_MOCK = "BUCKET_NAME_MOCK"; |
|
||||||
|
|
||||||
private static final String TENANT_CODE_MOCK = "TENANT_CODE_MOCK"; |
|
||||||
|
|
||||||
private static final String DIR_MOCK = "DIR_MOCK"; |
|
||||||
|
|
||||||
private static final String FILE_NAME_MOCK = "FILE_NAME_MOCK"; |
|
||||||
|
|
||||||
private static final String FILE_PATH_MOCK = "FILE_PATH_MOCK"; |
|
||||||
|
|
||||||
private static final String FULL_NAME = "/tmp/dir1/"; |
|
||||||
|
|
||||||
private static final String DEFAULT_PATH = "/tmp/"; |
|
||||||
|
|
||||||
@Mock |
|
||||||
private Storage gcsStorage; |
|
||||||
|
|
||||||
private GcsStorageOperator gcsStorageOperator; |
|
||||||
|
|
||||||
@BeforeEach |
|
||||||
public void setUp() throws Exception { |
|
||||||
gcsStorageOperator = Mockito.spy(GcsStorageOperator.class); |
|
||||||
Mockito.doReturn(CREDENTIAL_MOCK).when(gcsStorageOperator).readCredentials(); |
|
||||||
Mockito.doReturn(BUCKET_NAME_MOCK).when(gcsStorageOperator).readBucketName(); |
|
||||||
Mockito.doReturn(gcsStorage).when(gcsStorageOperator).buildGcsStorage(Mockito.anyString()); |
|
||||||
Mockito.doNothing().when(gcsStorageOperator).checkBucketNameExists(Mockito.anyString()); |
|
||||||
|
|
||||||
gcsStorageOperator.init(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testInit() throws Exception { |
|
||||||
verify(gcsStorageOperator, times(1)).buildGcsStorage(CREDENTIAL_MOCK); |
|
||||||
Assertions.assertEquals(CREDENTIAL_MOCK, gcsStorageOperator.getCredential()); |
|
||||||
Assertions.assertEquals(BUCKET_NAME_MOCK, gcsStorageOperator.getBucketName()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testClose() throws Exception { |
|
||||||
doNothing().when(gcsStorage).close(); |
|
||||||
gcsStorageOperator.close(); |
|
||||||
verify(gcsStorage, times(1)).close(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void createTenantResAndUdfDir() throws Exception { |
|
||||||
doReturn(DIR_MOCK).when(gcsStorageOperator).getGcsResDir(TENANT_CODE_MOCK); |
|
||||||
doReturn(DIR_MOCK).when(gcsStorageOperator).getGcsUdfDir(TENANT_CODE_MOCK); |
|
||||||
doReturn(true).when(gcsStorageOperator).mkdir(TENANT_CODE_MOCK, DIR_MOCK); |
|
||||||
gcsStorageOperator.createTenantDirIfNotExists(TENANT_CODE_MOCK); |
|
||||||
verify(gcsStorageOperator, times(2)).mkdir(TENANT_CODE_MOCK, DIR_MOCK); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getResDir() { |
|
||||||
final String expectedResourceDir = String.format("dolphinscheduler/%s/resources/", TENANT_CODE_MOCK); |
|
||||||
final String dir = gcsStorageOperator.getResDir(TENANT_CODE_MOCK); |
|
||||||
Assertions.assertEquals(expectedResourceDir, dir); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getUdfDir() { |
|
||||||
final String expectedUdfDir = String.format("dolphinscheduler/%s/udfs/", TENANT_CODE_MOCK); |
|
||||||
final String dir = gcsStorageOperator.getUdfDir(TENANT_CODE_MOCK); |
|
||||||
Assertions.assertEquals(expectedUdfDir, dir); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void mkdirWhenDirExists() { |
|
||||||
boolean isSuccess = false; |
|
||||||
try { |
|
||||||
final String key = DIR_MOCK + FOLDER_SEPARATOR; |
|
||||||
Mockito.doReturn(true).when(gcsStorageOperator).isObjectExists(key); |
|
||||||
isSuccess = gcsStorageOperator.mkdir(TENANT_CODE_MOCK, DIR_MOCK); |
|
||||||
|
|
||||||
} catch (IOException e) { |
|
||||||
Assertions.fail("test failed due to unexpected IO exception"); |
|
||||||
} |
|
||||||
|
|
||||||
Assertions.assertTrue(isSuccess); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void mkdirWhenDirNotExists() { |
|
||||||
boolean isSuccess = true; |
|
||||||
try { |
|
||||||
final String key = DIR_MOCK + FOLDER_SEPARATOR; |
|
||||||
doReturn(false).when(gcsStorageOperator).isObjectExists(key); |
|
||||||
isSuccess = gcsStorageOperator.mkdir(TENANT_CODE_MOCK, DIR_MOCK); |
|
||||||
verify(gcsStorage, times(1)).create(Mockito.any(BlobInfo.class), Mockito.any(byte[].class)); |
|
||||||
} catch (IOException e) { |
|
||||||
Assertions.fail("test failed due to unexpected IO exception"); |
|
||||||
} |
|
||||||
|
|
||||||
Assertions.assertTrue(isSuccess); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getResourceFullName() { |
|
||||||
final String expectedResourceFullName = |
|
||||||
String.format("dolphinscheduler/%s/resources/%s", TENANT_CODE_MOCK, FILE_NAME_MOCK); |
|
||||||
final String resourceFullName = gcsStorageOperator.getResourceFullName(TENANT_CODE_MOCK, FILE_NAME_MOCK); |
|
||||||
Assertions.assertEquals(expectedResourceFullName, resourceFullName); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getResourceFileName() { |
|
||||||
final String expectedResourceFileName = FILE_NAME_MOCK; |
|
||||||
final String resourceFullName = |
|
||||||
String.format("dolphinscheduler/%s/resources/%s", TENANT_CODE_MOCK, FILE_NAME_MOCK); |
|
||||||
final String resourceFileName = gcsStorageOperator.getResourceFileName(TENANT_CODE_MOCK, resourceFullName); |
|
||||||
Assertions.assertEquals(expectedResourceFileName, resourceFileName); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getFileName() { |
|
||||||
final String expectedFileName = |
|
||||||
String.format("dolphinscheduler/%s/resources/%s", TENANT_CODE_MOCK, FILE_NAME_MOCK); |
|
||||||
final String fileName = gcsStorageOperator.getFileName(ResourceType.FILE, TENANT_CODE_MOCK, FILE_NAME_MOCK); |
|
||||||
Assertions.assertEquals(expectedFileName, fileName); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void exists() { |
|
||||||
boolean doesExist = false; |
|
||||||
doReturn(true).when(gcsStorageOperator).isObjectExists(FILE_NAME_MOCK); |
|
||||||
try { |
|
||||||
doesExist = gcsStorageOperator.exists(FILE_NAME_MOCK); |
|
||||||
} catch (IOException e) { |
|
||||||
Assertions.fail("unexpected IO exception in unit test"); |
|
||||||
} |
|
||||||
|
|
||||||
Assertions.assertTrue(doesExist); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void delete() { |
|
||||||
boolean isDeleted = false; |
|
||||||
doReturn(true).when(gcsStorage).delete(Mockito.any(BlobId.class)); |
|
||||||
doReturn(true).when(gcsStorageOperator).isObjectExists(FILE_NAME_MOCK); |
|
||||||
try { |
|
||||||
isDeleted = gcsStorageOperator.delete(FILE_NAME_MOCK, true); |
|
||||||
} catch (IOException e) { |
|
||||||
Assertions.fail("unexpected IO exception in unit test"); |
|
||||||
} |
|
||||||
|
|
||||||
Assertions.assertTrue(isDeleted); |
|
||||||
verify(gcsStorage, times(1)).delete(Mockito.any(BlobId.class)); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void copy() { |
|
||||||
boolean isSuccess = false; |
|
||||||
doReturn(null).when(gcsStorage).copy(Mockito.any()); |
|
||||||
try { |
|
||||||
isSuccess = gcsStorageOperator.copy(FILE_PATH_MOCK, FILE_PATH_MOCK, false, false); |
|
||||||
} catch (IOException e) { |
|
||||||
Assertions.fail("unexpected IO exception in unit test"); |
|
||||||
} |
|
||||||
|
|
||||||
Assertions.assertTrue(isSuccess); |
|
||||||
verify(gcsStorage, times(1)).copy(Mockito.any()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void deleteTenant() { |
|
||||||
doNothing().when(gcsStorageOperator).deleteTenantCode(anyString()); |
|
||||||
try { |
|
||||||
gcsStorageOperator.deleteTenant(TENANT_CODE_MOCK); |
|
||||||
} catch (Exception e) { |
|
||||||
Assertions.fail("unexpected exception caught in unit test"); |
|
||||||
} |
|
||||||
|
|
||||||
verify(gcsStorageOperator, times(1)).deleteTenantCode(anyString()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getGcsResDir() { |
|
||||||
final String expectedGcsResDir = String.format("dolphinscheduler/%s/resources", TENANT_CODE_MOCK); |
|
||||||
final String gcsResDir = gcsStorageOperator.getGcsResDir(TENANT_CODE_MOCK); |
|
||||||
Assertions.assertEquals(expectedGcsResDir, gcsResDir); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getGcsUdfDir() { |
|
||||||
final String expectedGcsUdfDir = String.format("dolphinscheduler/%s/udfs", TENANT_CODE_MOCK); |
|
||||||
final String gcsUdfDir = gcsStorageOperator.getGcsUdfDir(TENANT_CODE_MOCK); |
|
||||||
Assertions.assertEquals(expectedGcsUdfDir, gcsUdfDir); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getGcsTenantDir() { |
|
||||||
final String expectedGcsTenantDir = String.format(FORMAT_S_S, DIR_MOCK, TENANT_CODE_MOCK); |
|
||||||
doReturn(DIR_MOCK).when(gcsStorageOperator).getGcsDataBasePath(); |
|
||||||
final String gcsTenantDir = gcsStorageOperator.getGcsTenantDir(TENANT_CODE_MOCK); |
|
||||||
Assertions.assertEquals(expectedGcsTenantDir, gcsTenantDir); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void deleteDir() { |
|
||||||
doReturn(true).when(gcsStorageOperator).isObjectExists(Mockito.any()); |
|
||||||
gcsStorageOperator.deleteDirectory(DIR_MOCK); |
|
||||||
verify(gcsStorage, times(1)).delete(Mockito.any(BlobId.class)); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testGetFileStatus() throws Exception { |
|
||||||
StorageEntity entity = |
|
||||||
gcsStorageOperator.getFileStatus(FULL_NAME, DEFAULT_PATH, TENANT_CODE_MOCK, ResourceType.FILE); |
|
||||||
Assertions.assertEquals(FULL_NAME, entity.getFullName()); |
|
||||||
Assertions.assertEquals("dir1/", entity.getFileName()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testListFilesStatus() throws Exception { |
|
||||||
Mockito.doReturn(null).when(gcsStorage).list(Mockito.any(), Mockito.any(Storage.BlobListOption.class), |
|
||||||
Mockito.any(Storage.BlobListOption.class)); |
|
||||||
List<StorageEntity> result = |
|
||||||
gcsStorageOperator.listFilesStatus(FULL_NAME, DEFAULT_PATH, TENANT_CODE_MOCK, ResourceType.FILE); |
|
||||||
verify(gcsStorage, times(1)).list(Mockito.any(), Mockito.any(Storage.BlobListOption.class), |
|
||||||
Mockito.any(Storage.BlobListOption.class)); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testListFilesStatusRecursively() throws Exception { |
|
||||||
StorageEntity entity = new StorageEntity(); |
|
||||||
entity.setFullName(FULL_NAME); |
|
||||||
|
|
||||||
doReturn(entity).when(gcsStorageOperator).getFileStatus(FULL_NAME, DEFAULT_PATH, TENANT_CODE_MOCK, |
|
||||||
ResourceType.FILE); |
|
||||||
doReturn(Collections.EMPTY_LIST).when(gcsStorageOperator).listFilesStatus(anyString(), anyString(), anyString(), |
|
||||||
Mockito.any(ResourceType.class)); |
|
||||||
|
|
||||||
List<StorageEntity> result = |
|
||||||
gcsStorageOperator.listFilesStatusRecursively(FULL_NAME, DEFAULT_PATH, TENANT_CODE_MOCK, |
|
||||||
ResourceType.FILE); |
|
||||||
Assertions.assertEquals(0, result.size()); |
|
||||||
} |
|
||||||
} |
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue