Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
19 changes: 13 additions & 6 deletions server/src/main/java/org/eclipse/openvsx/ExtensionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ public void reactivateExtensions(UserData user) {
var affectedExtensions = new LinkedHashSet<Extension>();
var versions = repositories.findVersionsByUser(user, false);
for (var version : versions) {
if (version.getState() == ExtensionVersion.State.DELETED) {
continue;
}
version.setActive(true);
affectedExtensions.add(version.getExtension());
}
Expand Down Expand Up @@ -236,7 +239,7 @@ public ResultJson deleteExtension(
HttpStatus.CONFLICT);
}

if (extension == null) {
if (extension == null || repositories.countVersions(namespaceName, extensionName) == 0) {
var message = "Extension not found: " + NamingUtil.toExtensionId(namespaceName, extensionName);
throw new ErrorResultException(message, HttpStatus.NOT_FOUND);
}
Expand All @@ -246,7 +249,13 @@ public ResultJson deleteExtension(
results.add(deleteExtension(user, extension));
} else {
for (var targetVersion : targetVersions) {
var extVersion = repositories.findVersion(user, targetVersion.version(), targetVersion.targetPlatform(), extensionName, namespaceName);
var extVersion = repositories.findVersion(
user,
targetVersion.version(),
targetVersion.targetPlatform(),
extensionName,
namespaceName
);
if (extVersion == null) {
var message = "Extension not found: " + NamingUtil.toLogFormat(namespaceName, extensionName, targetVersion.targetPlatform(), targetVersion.version());
throw new ErrorResultException(message, HttpStatus.NOT_FOUND);
Expand Down Expand Up @@ -293,8 +302,7 @@ protected ResultJson deleteExtension(UserData user, Extension extension) throws
cache.evictExtensionJsons(deprecatedExtension);
}

entityManager.remove(extension);
search.removeSearchEntry(extension);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: I'm removing this here since ExtensionService::updateExtension already removes the search entry if the active value is false

updateExtension(extension);

var result = ResultJson.success("Deleted " + NamingUtil.toExtensionId(extension));
logs.logAction(user, result);
Expand All @@ -304,7 +312,6 @@ protected ResultJson deleteExtension(UserData user, Extension extension) throws
protected ResultJson deleteExtension(UserData user, ExtensionVersion extVersion) {
var extension = extVersion.getExtension();
removeExtensionVersion(extVersion);
extension.getVersions().remove(extVersion);
updateExtension(extension);

var result = ResultJson.success("Deleted " + NamingUtil.toLogFormat(extVersion));
Expand All @@ -319,6 +326,6 @@ private void removeExtensionVersion(ExtensionVersion extVersion) {

repositories.findFiles(extVersion).map(RemoveFileJobRequest::new).forEach(scheduler::enqueue);
repositories.deleteFiles(extVersion);
entityManager.remove(extVersion);
extVersion.setState(ExtensionVersion.State.DELETED);
}
}
14 changes: 4 additions & 10 deletions server/src/main/java/org/eclipse/openvsx/admin/AdminService.java
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,12 @@ public void deleteExtensionAndDependencies(Extension extension, UserData admin,
cache.evictExtensionJsons(deprecatedExtension);
}

entityManager.remove(extension);
extensions.updateExtension(extension);

// evict the cache entries only after the changes have been commited
cache.evictExtensionJsons(extension);
cache.evictNamespaceDetails(extension);
cache.evictLatestExtensionVersion(extension);

search.removeSearchEntry(extension);
logs.logAction(admin, ResultJson.success("Deleted " + NamingUtil.toExtensionId(extension)));
}

Expand All @@ -188,7 +186,6 @@ protected void deleteExtensionAndDependencies(ExtensionVersion extVersion, UserD
}

removeExtensionVersion(extVersion);
extension.getVersions().remove(extVersion);
extensions.updateExtension(extension);
logs.logAction(admin, ResultJson.success("Deleted " + NamingUtil.toLogFormat(extVersion)));
}
Expand Down Expand Up @@ -219,7 +216,7 @@ public ResultJson deleteExtension(
public ResultJson deleteExtension(String namespaceName, String extensionName, UserData admin)
throws ErrorResultException {
var extension = repositories.findExtension(extensionName, namespaceName);
if (extension == null) {
if (extension == null || repositories.countVersions(namespaceName, extensionName) == 0) {
var extensionId = NamingUtil.toExtensionId(namespaceName, extensionName);
throw new ErrorResultException("Extension not found: " + extensionId, HttpStatus.NOT_FOUND);
}
Expand Down Expand Up @@ -270,15 +267,13 @@ protected ResultJson deleteExtension(Extension extension, UserData admin) throws
cache.evictExtensionJsons(deprecatedExtension);
}

entityManager.remove(extension);
extensions.updateExtension(extension);

// evict the cache entries only after the changes have been commited
cache.evictExtensionJsons(extension);
cache.evictNamespaceDetails(extension);
cache.evictLatestExtensionVersion(extension);

search.removeSearchEntry(extension);

var result = ResultJson.success("Deleted " + NamingUtil.toExtensionId(extension));
logs.logAction(admin, result);
return result;
Expand All @@ -287,7 +282,6 @@ protected ResultJson deleteExtension(Extension extension, UserData admin) throws
protected ResultJson deleteExtension(ExtensionVersion extVersion, UserData admin) {
var extension = extVersion.getExtension();
removeExtensionVersion(extVersion);
extension.getVersions().remove(extVersion);
extensions.updateExtension(extension);

var result = ResultJson.success("Deleted " + NamingUtil.toLogFormat(extVersion));
Expand Down Expand Up @@ -340,7 +334,7 @@ private void removeExtensionVersion(ExtensionVersion extVersion) {

repositories.findFiles(extVersion).map(RemoveFileJobRequest::new).forEach(scheduler::enqueue);
repositories.deleteFiles(extVersion);
entityManager.remove(extVersion);
extVersion.setState(ExtensionVersion.State.DELETED);
}

private String userNotFoundMessage(String user) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public enum Type {
EXTENDED
}

public enum State {
ACTIVE, INACTIVE, DELETED
}

@Id
@GeneratedValue(generator = "extensionVersionSeq")
@SequenceGenerator(name = "extensionVersionSeq", sequenceName = "extension_version_seq")
Expand Down Expand Up @@ -75,8 +79,20 @@ public enum Type {
@ManyToOne
private PersonalAccessToken publishedWith;

/**
* Legacy persisted mirror of {@link #state} kept for compatibility with active-based queries.
*
* @deprecated Use {@link #getState()} / {@link #setState(State)}. This field is planned for
* removal once repositories and SQL queries fully migrate to state-based filtering.
*/
@Deprecated(forRemoval = true)
private boolean active;

@Enumerated(EnumType.STRING)
private State state = State.ACTIVE;

private LocalDateTime lastUpdated = TimeUtil.getCurrentUTC();

private boolean potentiallyMalicious;

private String displayName;
Expand Down Expand Up @@ -313,12 +329,41 @@ public void setPublishedWith(PersonalAccessToken publishedWith) {
this.publishedWith = publishedWith;
}

/**
* @deprecated Use {@code getState() == State.ACTIVE}.
*/
@Deprecated(forRemoval = true)
public boolean isActive() {
return active;
return state == State.ACTIVE;
}

/**
* @deprecated Use {@link #setState(State)} with {@link State#ACTIVE} or {@link State#INACTIVE}.
*/
@Deprecated(forRemoval = true)
public void setActive(boolean active) {
this.active = active;
setState(active ? State.ACTIVE : State.INACTIVE);
}

public State getState() {
return state;
}

public void setState(State state) {
if (this.state == State.DELETED && state != State.DELETED) {
throw new IllegalStateException("Cannot transition away from DELETED state");
}
this.active = state == State.ACTIVE;
this.state = state;
this.lastUpdated = TimeUtil.getCurrentUTC();
}

public LocalDateTime getLastUpdated() {
return lastUpdated;
}

public void setLastUpdated(LocalDateTime lastUpdated) {
this.lastUpdated = lastUpdated;
}

public boolean isPotentiallyMalicious() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ private ExtensionVersion createExtensionVersion(ExtensionProcessor processor, Us

entityManager.persist(extension);
} else {
var existingVersion = repositories.findVersion(extVersion.getVersion(), extVersion.getTargetPlatform(), extension);
var existingVersion = repositories.findVersionIncludingDeleted(extVersion.getVersion(), extVersion.getTargetPlatform(), extension);
if (existingVersion != null) {
var extVersionId = NamingUtil.toLogFormat(namespaceName, extensionName, extVersion.getTargetPlatform(), extVersion.getVersion());
var message = "Extension " + extVersionId + " is already published";
Expand Down
Loading
Loading