From f5edcb69d36b749326863337aada97f8d7f1abff Mon Sep 17 00:00:00 2001 From: crschnick Date: Fri, 5 Jul 2024 15:31:52 +0000 Subject: [PATCH] Various fixes --- .../app/beacon/BeaconRequestHandler.java | 1 + .../impl/ConnectionInfoExchangeImpl.java | 1 + .../impl/ConnectionRemoveExchangeImpl.java | 26 +++ .../browser/BrowserBookmarkHeaderComp.java | 5 +- .../xpipe/app/comp/base/SideMenuBarComp.java | 4 +- .../main/java/io/xpipe/app/core/AppTheme.java | 5 + app/src/main/java/module-info.java | 1 + .../io/xpipe/app/resources/misc/api.md | 217 +++++++++++++++++- .../io/xpipe/app/resources/style/browser.css | 3 +- .../io/xpipe/app/resources/style/prefs.css | 5 + .../xpipe/app/resources/style/scrollbar.css | 6 +- .../app/resources/style/store-entry-comp.css | 2 +- .../app/resources/theme/cupertinoDark.css | 2 +- .../app/resources/theme/cupertinoLight.css | 1 + .../io/xpipe/app/resources/theme/dracula.css | 1 + .../io/xpipe/app/resources/theme/light.css | 2 +- .../io/xpipe/app/resources/theme/mocha.css | 1 + .../io/xpipe/app/resources/theme/nordDark.css | 2 +- .../xpipe/app/resources/theme/nordLight.css | 1 + .../beacon/api/ConnectionInfoExchange.java | 4 + .../beacon/api/ConnectionRemoveExchange.java | 31 +++ beacon/src/main/java/module-info.java | 1 + openapi.yaml | 51 +++- 23 files changed, 353 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/io/xpipe/app/beacon/impl/ConnectionRemoveExchangeImpl.java create mode 100644 app/src/main/resources/io/xpipe/app/resources/theme/cupertinoLight.css create mode 100644 app/src/main/resources/io/xpipe/app/resources/theme/dracula.css create mode 100644 app/src/main/resources/io/xpipe/app/resources/theme/nordLight.css create mode 100644 beacon/src/main/java/io/xpipe/beacon/api/ConnectionRemoveExchange.java diff --git a/app/src/main/java/io/xpipe/app/beacon/BeaconRequestHandler.java b/app/src/main/java/io/xpipe/app/beacon/BeaconRequestHandler.java index bd9dfffbc..d231c96a0 100644 --- a/app/src/main/java/io/xpipe/app/beacon/BeaconRequestHandler.java +++ b/app/src/main/java/io/xpipe/app/beacon/BeaconRequestHandler.java @@ -110,6 +110,7 @@ public class BeaconRequestHandler implements HttpHandler { .replace("$RequestBuilder", "") .replace("Exchange$Request","Request") .replace("at [Source: UNKNOWN; byte offset: #UNKNOWN]", "") + .replaceAll("(\\w+) is marked non-null but is null", "field $1 is missing from object") .trim(); writeError(exchange, new BeaconClientErrorResponse(message), 400); } diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/ConnectionInfoExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/ConnectionInfoExchangeImpl.java index a07e87b68..d0dda79b1 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/ConnectionInfoExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/ConnectionInfoExchangeImpl.java @@ -37,6 +37,7 @@ public class ConnectionInfoExchangeImpl extends ConnectionInfoExchange { .usageCategory(e.getProvider().getUsageCategory()) .type(e.getProvider().getId()) .state(e.getStorePersistentState() != null ? e.getStorePersistentState() : new Object()) + .cache(e.getStoreCache()) .build(); list.add(apply); } diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/ConnectionRemoveExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/ConnectionRemoveExchangeImpl.java new file mode 100644 index 000000000..88f3850cb --- /dev/null +++ b/app/src/main/java/io/xpipe/app/beacon/impl/ConnectionRemoveExchangeImpl.java @@ -0,0 +1,26 @@ +package io.xpipe.app.beacon.impl; + +import com.sun.net.httpserver.HttpExchange; +import io.xpipe.app.storage.DataStorage; +import io.xpipe.app.storage.DataStoreEntry; +import io.xpipe.beacon.BeaconClientException; +import io.xpipe.beacon.api.ConnectionRemoveExchange; + +import java.util.ArrayList; +import java.util.UUID; + +public class ConnectionRemoveExchangeImpl extends ConnectionRemoveExchange { + + @Override + public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException { + var entries = new ArrayList(); + for (UUID uuid : msg.getConnections()) { + var e = DataStorage.get() + .getStoreEntryIfPresent(uuid) + .orElseThrow(() -> new BeaconClientException("Unknown connection: " + uuid)); + entries.add(e); + } + DataStorage.get().deleteWithChildren(entries.toArray(DataStoreEntry[]::new)); + return Response.builder().build(); + } +} diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserBookmarkHeaderComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserBookmarkHeaderComp.java index 71e3c1c4c..14f3d5050 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserBookmarkHeaderComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserBookmarkHeaderComp.java @@ -30,8 +30,9 @@ public final class BrowserBookmarkHeaderComp extends SimpleComp { StoreViewState.get().getAllConnectionsCategory(), StoreViewState.get().getActiveCategory(), this.category) - .styleClass(Styles.LEFT_PILL); - var filter = new FilterComp(this.filter).styleClass(Styles.RIGHT_PILL).hgrow(); + .styleClass(Styles.LEFT_PILL) + .minWidth(Region.USE_PREF_SIZE); + var filter = new FilterComp(this.filter).styleClass(Styles.RIGHT_PILL).minWidth(0).hgrow(); var top = new HorizontalComp(List.of(category, filter)) .apply(struc -> struc.get().setFillHeight(true)) diff --git a/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java b/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java index 6bb76656b..a5e9586a1 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java @@ -45,14 +45,14 @@ public class SideMenuBarComp extends Comp> { var selectedBorder = Bindings.createObjectBinding( () -> { var c = Platform.getPreferences().getAccentColor().desaturate(); - return new Background(new BackgroundFill(c,new CornerRadii(8), new Insets(5, 1, 5, 2))); + return new Background(new BackgroundFill(c,new CornerRadii(8), new Insets(10, 1, 10, 2))); }, Platform.getPreferences().accentColorProperty()); var hoverBorder = Bindings.createObjectBinding( () -> { var c = Platform.getPreferences().getAccentColor().darker().desaturate(); - return new Background(new BackgroundFill(c,new CornerRadii(8), new Insets(5, 1, 5, 2))); + return new Background(new BackgroundFill(c,new CornerRadii(8), new Insets(10, 1, 10, 2))); }, Platform.getPreferences().accentColorProperty()); diff --git a/app/src/main/java/io/xpipe/app/core/AppTheme.java b/app/src/main/java/io/xpipe/app/core/AppTheme.java index 34f84ac85..bfc1c8308 100644 --- a/app/src/main/java/io/xpipe/app/core/AppTheme.java +++ b/app/src/main/java/io/xpipe/app/core/AppTheme.java @@ -204,6 +204,11 @@ public class AppTheme { Application.setUserAgentStylesheet(Styles.toDataURI(builder.toString())); } + + public List getAdditionalStylesheets() { + return List.of(); + } + @Override public ObservableValue toTranslatedString() { return new SimpleStringProperty(name); diff --git a/app/src/main/java/module-info.java b/app/src/main/java/module-info.java index d04990eff..2923838ea 100644 --- a/app/src/main/java/module-info.java +++ b/app/src/main/java/module-info.java @@ -135,6 +135,7 @@ open module io.xpipe.app { ShellExecExchangeImpl, ConnectionQueryExchangeImpl, ConnectionInfoExchangeImpl, + ConnectionRemoveExchangeImpl, ConnectionAddExchangeImpl, ConnectionBrowseExchangeImpl, ConnectionTerminalExchangeImpl, diff --git a/app/src/main/resources/io/xpipe/app/resources/misc/api.md b/app/src/main/resources/io/xpipe/app/resources/misc/api.md index d548fda10..032417a5d 100644 --- a/app/src/main/resources/io/xpipe/app/resources/misc/api.md +++ b/app/src/main/resources/io/xpipe/app/resources/misc/api.md @@ -623,6 +623,7 @@ curl -X POST http://localhost:21721/connection/info \ `POST /connection/add` Creates the new connection in the xpipe vault from raw json data. +This can also perform an optional validation first to make sure that the connection can be established. If an equivalent connection already exists, no new one will be added. @@ -631,6 +632,7 @@ If an equivalent connection already exists, no new one will be added. ```json { "name": "my connection", + "validate": true, "category": "97458c07-75c0-4f9d-a06e-92d8cdf67c40", "data": { "type": "shellEnvironment", @@ -690,6 +692,7 @@ bearerAuth ```javascript const inputBody = '{ "name": "my connection", + "validate": true, "category": "97458c07-75c0-4f9d-a06e-92d8cdf67c40", "data": { "type": "shellEnvironment", @@ -732,6 +735,7 @@ headers = { data = """ { "name": "my connection", + "validate": true, "category": "97458c07-75c0-4f9d-a06e-92d8cdf67c40", "data": { "type": "shellEnvironment", @@ -762,6 +766,7 @@ var request = HttpRequest .POST(HttpRequest.BodyPublishers.ofString(""" { "name": "my connection", + "validate": true, "category": "97458c07-75c0-4f9d-a06e-92d8cdf67c40", "data": { "type": "shellEnvironment", @@ -815,6 +820,7 @@ curl -X POST http://localhost:21721/connection/add \ --data ' { "name": "my connection", + "validate": true, "category": "97458c07-75c0-4f9d-a06e-92d8cdf67c40", "data": { "type": "shellEnvironment", @@ -832,6 +838,174 @@ curl -X POST http://localhost:21721/connection/add \ +## Remove connection + + + +`POST /connection/remove` + +Removes a set of connection. This includes any possible children associated with the connection. + +Some connections, for example the local machine, can not be removed. + +> Body parameter + +```json +{ + "connections": [ + "36ad9716-a209-4f7f-9814-078d3349280c" + ] +} +``` + +

Parameters

+ +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|body|body|[ConnectionRemoveRequest](#schemaconnectionremoverequest)|true|none| + +> Example responses + +> 400 Response + +```json +{ + "message": "string" +} +``` + +

Responses

+ +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|The removal was successful.|None| +|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|Bad request. Please check error message and your parameters.|[ClientErrorResponse](#schemaclienterrorresponse)| +|401|[Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1)|Authorization failed. Please supply a `Bearer` token via the `Authorization` header.|None| +|403|[Forbidden](https://tools.ietf.org/html/rfc7231#section-6.5.3)|Authorization failed. Please supply a valid `Bearer` token via the `Authorization` header.|None| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|Internal error.|[ServerErrorResponse](#schemaservererrorresponse)| + + + +
+ +Code samples + +```javascript +const inputBody = '{ + "connections": [ + "36ad9716-a209-4f7f-9814-078d3349280c" + ] +}'; +const headers = { + 'Content-Type':'application/json', + 'Accept':'application/json', + 'Authorization':'Bearer {access-token}' +}; + +fetch('http://localhost:21721/connection/remove', +{ + method: 'POST', + body: inputBody, + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +```python +import requests +headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': 'Bearer {access-token}' +} + +data = """ +{ + "connections": [ + "36ad9716-a209-4f7f-9814-078d3349280c" + ] +} +""" +r = requests.post('http://localhost:21721/connection/remove', headers = headers, data = data) + +print(r.json()) + +``` + +```java +var uri = URI.create("http://localhost:21721/connection/remove"); +var client = HttpClient.newHttpClient(); +var request = HttpRequest + .newBuilder() + .uri(uri) + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .header("Authorization", "Bearer {access-token}") + .POST(HttpRequest.BodyPublishers.ofString(""" +{ + "connections": [ + "36ad9716-a209-4f7f-9814-078d3349280c" + ] +} + """)) + .build(); +var response = client.send(request, HttpResponse.BodyHandlers.ofString()); +System.out.println(response.statusCode()); +System.out.println(response.body()); + +``` + +```go +package main + +import ( + "bytes" + "net/http" +) + +func main() { + + headers := map[string][]string{ + "Content-Type": []string{"application/json"}, + "Accept": []string{"application/json"}, + "Authorization": []string{"Bearer {access-token}"}, + } + + data := bytes.NewBuffer([]byte{jsonReq}) + req, err := http.NewRequest("POST", "http://localhost:21721/connection/remove", data) + req.Header = headers + + client := &http.Client{} + resp, err := client.Do(req) + // ... +} + +``` + +```shell +# You can also use wget +curl -X POST http://localhost:21721/connection/remove \ + -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer {access-token}' \ + --data ' +{ + "connections": [ + "36ad9716-a209-4f7f-9814-078d3349280c" + ] +} +' + +``` + +
+ ## Open connection in file browser @@ -1307,7 +1481,7 @@ curl -X POST http://localhost:21721/connection/toggle \ -## Refreshes state of a connection +## Refresh state of a connection @@ -1325,7 +1499,7 @@ This will update the connection state information and also any children if the c } ``` -

Parameters

+

Parameters

|Name|In|Type|Required|Description| |---|---|---|---|---| @@ -1341,7 +1515,7 @@ This will update the connection state information and also any children if the c } ``` -

Responses

+

Responses

|Status|Meaning|Description|Schema| |---|---|---|---| @@ -2644,7 +2818,8 @@ Retrieves version information from the daemon "version": "string", "canonicalVersion": "string", "buildVersion": "string", - "jvmVersion": "string" + "jvmVersion": "string", + "pro": true } ``` @@ -3072,7 +3247,8 @@ undefined "usageCategory": "shell", "lastModified": "string", "lastUsed": "string", - "state": {} + "state": {}, + "cache": {} } ] @@ -3091,6 +3267,7 @@ undefined |lastModified|string|true|none|The timestamp of when the connection configuration was last modified in ISO 8601| |lastUsed|string|true|none|The timestamp of when the connection was last launched in ISO 8601| |state|object|true|none|The internal persistent state information about the connection| +|cache|object|true|none|The temporary cache data for the connection| #### Enumerated Values @@ -3134,7 +3311,8 @@ undefined ```json { "name": "string", - "data": {} + "data": {}, + "validate": true } ``` @@ -3145,6 +3323,7 @@ undefined |---|---|---|---|---| |name|string|true|none|The connection name| |data|object|true|none|The raw connection store data. Schemas for connection types are not documented but you can find the connection data of your existing connections in the xpipe vault.| +|validate|boolean|true|none|Whether to perform a connection validation before adding it, i.e., probe the connection first. If validation is enabled and fails, the connection will not be added|

ConnectionAddResponse

@@ -3166,6 +3345,28 @@ undefined |---|---|---|---|---| |connection|string|true|none|The connection uuid| +

ConnectionRemoveRequest

+ + + + + + +```json +{ + "connections": [ + "string" + ] +} + +``` + +

Properties

+ +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|connections|[string]|true|none|The connections to remove| +

ConnectionBrowseRequest

@@ -3291,7 +3492,8 @@ undefined "version": "string", "canonicalVersion": "string", "buildVersion": "string", - "jvmVersion": "string" + "jvmVersion": "string", + "pro": true } ``` @@ -3304,6 +3506,7 @@ undefined |canonicalVersion|string|true|none|The canonical version of the running daemon| |buildVersion|string|true|none|The build timestamp| |jvmVersion|string|true|none|The version of the Java Virtual Machine in which the daemon is running| +|pro|boolean|true|none|Whether the daemon supports professional edition features|

AuthMethod

diff --git a/app/src/main/resources/io/xpipe/app/resources/style/browser.css b/app/src/main/resources/io/xpipe/app/resources/style/browser.css index f293bee56..c7a2f25c8 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/browser.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/browser.css @@ -52,8 +52,9 @@ .browser .welcome { -fx-border-color: -color-bg-inset, -color-border-default; - -fx-border-width: 2.65em 0 0 0, 0.05em 0 0 0; + -fx-border-width: 2.65em 10 0 0, 0.05em 0 0 0; -fx-border-insets: 0, 2.65em 0 0 0; + -fx-border-radius: 0 10 0 0, 0; } .root:seamless-frame .browser .welcome { diff --git a/app/src/main/resources/io/xpipe/app/resources/style/prefs.css b/app/src/main/resources/io/xpipe/app/resources/style/prefs.css index 19e314289..d6ceeff26 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/prefs.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/prefs.css @@ -65,3 +65,8 @@ .prefs .theme-switcher .combo-box-popup .list-view { -fx-effect: NONE; } + + +.root:seamless-frame .prefs .scroll-bar:vertical { + -fx-padding: 9 1 5 1; +} diff --git a/app/src/main/resources/io/xpipe/app/resources/style/scrollbar.css b/app/src/main/resources/io/xpipe/app/resources/style/scrollbar.css index 05cf4145f..b17e429ba 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/scrollbar.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/scrollbar.css @@ -1,7 +1,7 @@ .scroll-bar:vertical { - -fx-min-width: 0.4em; - -fx-pref-width: 0.4em; - -fx-padding: 0.1em 1 0.1em 1; + -fx-min-width: 6px; + -fx-pref-width: 6px; + -fx-padding: 1; -fx-background-color: transparent; } diff --git a/app/src/main/resources/io/xpipe/app/resources/style/store-entry-comp.css b/app/src/main/resources/io/xpipe/app/resources/style/store-entry-comp.css index cab2e49b5..37894e7f6 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/store-entry-comp.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/store-entry-comp.css @@ -8,7 +8,7 @@ } .store-list-comp.scroll-pane .scroll-bar:vertical { - -fx-padding: 0.6em 1 0.3em 1; + -fx-padding: 9 1 5 1; } /* Grid */ diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/cupertinoDark.css b/app/src/main/resources/io/xpipe/app/resources/theme/cupertinoDark.css index e27a340b5..c60247759 100644 --- a/app/src/main/resources/io/xpipe/app/resources/theme/cupertinoDark.css +++ b/app/src/main/resources/io/xpipe/app/resources/theme/cupertinoDark.css @@ -1 +1 @@ -.root { -color-bg-default-transparent: #0d1117d2; } \ No newline at end of file +.root { -color-bg-default-transparent: #1C1C1ED2; } \ No newline at end of file diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/cupertinoLight.css b/app/src/main/resources/io/xpipe/app/resources/theme/cupertinoLight.css new file mode 100644 index 000000000..fbbefc2be --- /dev/null +++ b/app/src/main/resources/io/xpipe/app/resources/theme/cupertinoLight.css @@ -0,0 +1 @@ +.root { -color-bg-default-transparent: #FFFFFFCC; } \ No newline at end of file diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/dracula.css b/app/src/main/resources/io/xpipe/app/resources/theme/dracula.css new file mode 100644 index 000000000..98caee1a0 --- /dev/null +++ b/app/src/main/resources/io/xpipe/app/resources/theme/dracula.css @@ -0,0 +1 @@ +.root { -color-bg-default-transparent: #282a36D2; } \ No newline at end of file diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/light.css b/app/src/main/resources/io/xpipe/app/resources/theme/light.css index ea72bdf67..fbbefc2be 100644 --- a/app/src/main/resources/io/xpipe/app/resources/theme/light.css +++ b/app/src/main/resources/io/xpipe/app/resources/theme/light.css @@ -1 +1 @@ -.root { -color-bg-default-transparent: #FFFFFF99; } \ No newline at end of file +.root { -color-bg-default-transparent: #FFFFFFCC; } \ No newline at end of file diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/mocha.css b/app/src/main/resources/io/xpipe/app/resources/theme/mocha.css index fece551f3..a6a726520 100644 --- a/app/src/main/resources/io/xpipe/app/resources/theme/mocha.css +++ b/app/src/main/resources/io/xpipe/app/resources/theme/mocha.css @@ -56,6 +56,7 @@ -color-fg-subtle: rgb(166, 173, 200); -color-fg-emphasis: rgb(180, 190, 254); -color-bg-default: rgb(30, 30, 46); + -color-bg-default-transparent: #1E1E2ED2; -color-bg-overlay: rgb(24, 24, 37); -color-bg-subtle: rgb(49, 50, 68); -color-bg-inset: rgb(17, 17, 27); diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/nordDark.css b/app/src/main/resources/io/xpipe/app/resources/theme/nordDark.css index e27a340b5..971cb51fa 100644 --- a/app/src/main/resources/io/xpipe/app/resources/theme/nordDark.css +++ b/app/src/main/resources/io/xpipe/app/resources/theme/nordDark.css @@ -1 +1 @@ -.root { -color-bg-default-transparent: #0d1117d2; } \ No newline at end of file +.root { -color-bg-default-transparent: #2E3440d2; } \ No newline at end of file diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/nordLight.css b/app/src/main/resources/io/xpipe/app/resources/theme/nordLight.css new file mode 100644 index 000000000..a663e3dd9 --- /dev/null +++ b/app/src/main/resources/io/xpipe/app/resources/theme/nordLight.css @@ -0,0 +1 @@ +.root { -color-bg-default-transparent: #fafafcCC; } \ No newline at end of file diff --git a/beacon/src/main/java/io/xpipe/beacon/api/ConnectionInfoExchange.java b/beacon/src/main/java/io/xpipe/beacon/api/ConnectionInfoExchange.java index 91a69928a..67d09d1b1 100644 --- a/beacon/src/main/java/io/xpipe/beacon/api/ConnectionInfoExchange.java +++ b/beacon/src/main/java/io/xpipe/beacon/api/ConnectionInfoExchange.java @@ -10,6 +10,7 @@ import lombok.extern.jackson.Jacksonized; import java.time.Instant; import java.util.List; +import java.util.Map; import java.util.UUID; public class ConnectionInfoExchange extends BeaconInterface { @@ -65,5 +66,8 @@ public class ConnectionInfoExchange extends BeaconInterface cache; } } diff --git a/beacon/src/main/java/io/xpipe/beacon/api/ConnectionRemoveExchange.java b/beacon/src/main/java/io/xpipe/beacon/api/ConnectionRemoveExchange.java new file mode 100644 index 000000000..600f443d8 --- /dev/null +++ b/beacon/src/main/java/io/xpipe/beacon/api/ConnectionRemoveExchange.java @@ -0,0 +1,31 @@ +package io.xpipe.beacon.api; + +import io.xpipe.beacon.BeaconInterface; +import lombok.Builder; +import lombok.NonNull; +import lombok.Value; +import lombok.extern.jackson.Jacksonized; + +import java.util.List; +import java.util.UUID; + +public class ConnectionRemoveExchange extends BeaconInterface { + + @Override + public String getPath() { + return "/connection/remove"; + } + + @Jacksonized + @Builder + @Value + public static class Request { + @NonNull + List connections; + } + + @Jacksonized + @Builder + @Value + public static class Response {} +} diff --git a/beacon/src/main/java/module-info.java b/beacon/src/main/java/module-info.java index c5ba7fccc..30a277cb6 100644 --- a/beacon/src/main/java/module-info.java +++ b/beacon/src/main/java/module-info.java @@ -38,6 +38,7 @@ open module io.xpipe.beacon { HandshakeExchange, ConnectionQueryExchange, ConnectionInfoExchange, + ConnectionRemoveExchange, ConnectionAddExchange, ConnectionBrowseExchange, ConnectionTerminalExchange, diff --git a/openapi.yaml b/openapi.yaml index 4e1f1dcc4..d8547f806 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -158,6 +158,7 @@ paths: summary: Add new connection description: | Creates the new connection in the xpipe vault from raw json data. + This can also perform an optional validation first to make sure that the connection can be established. If an equivalent connection already exists, no new one will be added. operationId: connectionAdd @@ -170,7 +171,7 @@ paths: examples: simple: summary: Add new pwsh shell environment - value: { "name": "my connection", "category": "97458c07-75c0-4f9d-a06e-92d8cdf67c40", "data": + value: { "name": "my connection", "validate": true, "category": "97458c07-75c0-4f9d-a06e-92d8cdf67c40", "data": { "type": "shellEnvironment", "commands": null, @@ -200,6 +201,35 @@ paths: $ref: '#/components/responses/Forbidden' '500': $ref: '#/components/responses/InternalServerError' + /connection/remove: + post: + summary: Remove connection + description: | + Removes a set of connection. This includes any possible children associated with the connection. + + Some connections, for example the local machine, can not be removed. + operationId: connectionRemove + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ConnectionRemoveRequest' + examples: + simple: + summary: Remove single connection + value: { "connections": [ "36ad9716-a209-4f7f-9814-078d3349280c" ] } + responses: + '200': + description: The removal was successful. + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' /connection/browse: post: summary: Open connection in file browser @@ -779,6 +809,9 @@ components: state: type: object description: The internal persistent state information about the connection + cache: + type: object + description: The temporary cache data for the connection required: - connection - category @@ -789,6 +822,7 @@ components: - lastUsed - lastModified - state + - cache ConnectionRefreshRequest: type: object properties: @@ -806,9 +840,13 @@ components: data: type: object description: The raw connection store data. Schemas for connection types are not documented but you can find the connection data of your existing connections in the xpipe vault. + validate: + type: boolean + description: Whether to perform a connection validation before adding it, i.e., probe the connection first. If validation is enabled and fails, the connection will not be added required: - name - data + - validate ConnectionAddResponse: type: object properties: @@ -817,6 +855,17 @@ components: description: The connection uuid required: - connection + ConnectionRemoveRequest: + type: object + properties: + connections: + type: array + description: The connections to remove + items: + type: string + description: The unique id of the connection + required: + - connections ConnectionBrowseRequest: type: object properties: