Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
*/
package io.cloudbeaver.model.rm.local;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.cloudbeaver.BaseWebProjectImpl;
import io.cloudbeaver.DBWConstants;
import io.cloudbeaver.model.app.ServletApplication;
Expand Down Expand Up @@ -48,6 +50,8 @@
import org.jkiss.utils.Pair;

import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.text.MessageFormat;
import java.time.OffsetDateTime;
Expand All @@ -63,6 +67,10 @@
public class LocalResourceController extends BaseLocalResourceController {

private static final Log log = Log.getLog(LocalResourceController.class);
private static final Gson GSON = new GsonBuilder()
.setPrettyPrinting()
.create();
private static final String PROJECT_INFO_CONF = ".project-info.conf";

protected final SMCredentialsProvider credentialsProvider;

Expand Down Expand Up @@ -295,6 +303,29 @@ public RMProject createProject(@NotNull String name, @Nullable String descriptio
}
}

@Override
public RMProject updateProject(@NotNull String projectId, @NotNull RMProjectInfo projectInfo) throws DBException {
try (var projectLock = lockController.lock(projectId, "updateProject")) {
RMProject project = getProject(projectId, false, false);
Path targetPath = getProjectPath(projectId);
if (!Files.exists(targetPath)) {
throw new DBException("Project folder '" + projectId + "' not found");
}
if (CommonUtils.isEmpty(projectInfo.getName())) {
throw new DBException("Project name required");
}
try {
String config = GSON.toJson(projectInfo);
Files.writeString(targetPath.resolve(PROJECT_INFO_CONF), config);
project.setName(projectInfo.getName());
project.setDescription(projectInfo.getDescription());
return project;
} catch (IOException e) {
throw new DBException("Error writing project info", e);
}
}
}

@Override
public void deleteProject(@NotNull String projectId) throws DBException {
try (var projectLock = lockController.lock(projectId, "deleteProject")) {
Expand Down Expand Up @@ -735,8 +766,9 @@ private RMProject makeProjectFromPath(Path path, Set<RMProjectPermission> permis
.toArray(String[]::new);

RMProject project = new RMProject();
String projectName = path.getFileName().toString();
project.setName(projectName);
RMProjectInfo projectMetadata = readProjectInfo(path);
project.setName(projectMetadata.getName());
project.setDescription(projectMetadata.getDescription());
project.setId(makeProjectIdFromPath(path, type));
project.setType(type);
project.setProjectPermissions(allProjectPermissions);
Expand All @@ -758,6 +790,19 @@ private RMProject makeProjectFromPath(Path path, Set<RMProjectPermission> permis
return project;
}

@NotNull
private RMProjectInfo readProjectInfo(@NotNull Path projectPath) {
Path projectInfoPath = projectPath.resolve(PROJECT_INFO_CONF);
if (Files.exists(projectInfoPath)) {
try (Reader reader = Files.newBufferedReader(projectInfoPath, StandardCharsets.UTF_8)) {
return GSON.fromJson(reader, RMProjectInfo.class);
} catch (IOException e) {
log.error("Error reading project information from " + projectInfoPath, e);
}
}
return new RMProjectInfo(projectPath.getFileName().toString(), null);
}

private void createResourceTypeFolders(Path path) {
// FIXME: do not create folders by force!!!
var resourceTypes = ResourceTypeRegistry.getInstance().getResourceTypes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ extend type Mutation {
description: String
): RMProject!

"Updates project with the specified projectId. If projectName is not specified then does not change it."
rmUpdateProject(
projectId: ID!,
projectName: String,
description: String
): RMProject!

"Deletes project by projectId. Returns true if project was deleted, false if project not found"
rmDeleteProject(projectId: ID!): Boolean!

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ RMProject createProject(
@NotNull String name,
@Nullable String description) throws DBWebException;

@WebAction(requirePermissions = {RMConstants.PERMISSION_RM_ADMIN})
RMProject updateProject(
@NotNull WebSession session,
@NotNull String projectId,
@Nullable String name,
@Nullable String description
) throws DBWebException;

@WebAction(requirePermissions = {RMConstants.PERMISSION_RM_ADMIN})
boolean deleteProject(
@NotNull WebSession session,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ public void bindWiring(DBWBindingContext model) throws DBWebException {
env.getArgument("projectName"),
env.getArgument("description")
))
.dataFetcher(
"rmUpdateProject", env -> getService(env).updateProject(
getWebSession(env),
getProjectReference(env),
env.getArgument("projectName"),
env.getArgument("description")
)
)
.dataFetcher("rmDeleteProject", env -> getService(env).deleteProject(
getWebSession(env),
getProjectReference(env)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.rm.RMController;
import org.jkiss.dbeaver.model.rm.RMProject;
import org.jkiss.dbeaver.model.rm.RMProjectInfo;
import org.jkiss.dbeaver.model.rm.RMResource;
import org.jkiss.dbeaver.model.secret.DBSSecretController;
import org.jkiss.dbeaver.model.security.*;
Expand Down Expand Up @@ -266,6 +267,33 @@ public RMProject createProject(
}
}

@Override
public RMProject updateProject(
@NotNull WebSession session,
@NotNull String projectId,
@Nullable String name,
@Nullable String description
) throws DBWebException {
try {
var project = session.getProjectById(projectId);
if (project == null) {
throw new DBException("Project not found: " + projectId);
}
RMProjectInfo projectInfo = new RMProjectInfo();
projectInfo.setName(name == null ? project.getRMProject().getName() : name);
projectInfo.setDescription(description == null ? project.getRMProject().getDescription() : description);
RMProject rmProject = getResourceController(session).updateProject(projectId, projectInfo);
project.getRMProject().setName(rmProject.getName());
project.getRMProject().setDescription(rmProject.getDescription());
ServletAppUtils.getServletApplication().getEventController().addEvent(
WSProjectUpdateEvent.update(session.getSessionId(), session.getUserId(), rmProject.getId())
);
return rmProject;
} catch (DBException e) {
throw new DBWebException("Error creating project", e);
}
}

@Override
public boolean deleteProject(@NotNull WebSession session, @NotNull String projectId) throws DBWebException {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
* Copyright (C) 2020-2025 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -112,6 +112,17 @@ export class SharedProjectsResource extends CachedMapResource<string, SharedProj
return this.get(project.id)!;
}

async update(config: IProjectConfig): Promise<SharedProject> {
const { project } = await this.graphQLService.sdk.updateProject({
projectId: config.id,
projectName: config.name,
});

this.set(project.id, project as SharedProject);

return this.get(project.id)!;
}

async deleteProject(id: string): Promise<void>;
async deleteProject(id: ResourceKeyList<string>): Promise<void>;
async deleteProject(key: ResourceKey<string>): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mutation updateProject($projectId: ID!, $projectName: String, $description: String) {
project: rmUpdateProject(projectId: $projectId, projectName: $projectName, description: $description) {
...SharedProject
}
}
Loading