mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-22 07:30:24 +00:00
Rework password handling
This commit is contained in:
parent
f8b56ab774
commit
3d32d6cd84
12 changed files with 179 additions and 68 deletions
|
@ -14,7 +14,7 @@ public class AskpassExchangeImpl extends AskpassExchange
|
|||
OperationMode.switchTo(OperationMode.TRAY);
|
||||
}
|
||||
|
||||
var r = AskpassAlert.query(msg.getPrompt(), msg.getRequest(), msg.getId());
|
||||
var r = AskpassAlert.query(msg.getPrompt(), msg.getRequest(), msg.getStoreId(), msg.getSubId());
|
||||
return Response.builder().value(r != null ? r.getSecretValue() : null).build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,16 +15,17 @@ public class AskpassAlert {
|
|||
private static final Set<UUID> cancelledRequests = new HashSet<>();
|
||||
private static final Set<UUID> requests = new HashSet<>();
|
||||
|
||||
public static SecretValue query(String prompt, UUID requestId, UUID secretId) {
|
||||
public static SecretValue query(String prompt, UUID requestId, UUID secretId, int sub) {
|
||||
if (cancelledRequests.contains(requestId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (SecretCache.get(secretId).isPresent() && requests.contains(requestId)) {
|
||||
SecretCache.clear(secretId);
|
||||
var ref = new SecretManager.SecretReference(secretId, sub);
|
||||
if (SecretManager.get(ref).isPresent() && requests.contains(requestId)) {
|
||||
SecretManager.clear(ref);
|
||||
}
|
||||
|
||||
var found = SecretCache.get(secretId);
|
||||
var found = SecretManager.get(ref);
|
||||
if (found.isPresent()) {
|
||||
return found.get();
|
||||
}
|
||||
|
@ -49,7 +50,7 @@ public class AskpassAlert {
|
|||
// If the result is null, assume that the operation was aborted by the user
|
||||
if (r != null) {
|
||||
requests.add(requestId);
|
||||
SecretCache.set(secretId, r);
|
||||
SecretManager.set(ref, r);
|
||||
} else {
|
||||
cancelledRequests.add(requestId);
|
||||
}
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
package io.xpipe.app.util;
|
||||
|
||||
import io.xpipe.core.util.SecretValue;
|
||||
import io.xpipe.core.util.UuidHelper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SecretCache {
|
||||
|
||||
private static final Map<UUID, SecretValue> passwords = new HashMap<>();
|
||||
|
||||
public static SecretValue retrieve(SecretRetrievalStrategy strategy, String prompt, Object key) throws Exception {
|
||||
var id = UuidHelper.generateFromObject(key);
|
||||
if (passwords.containsKey(id)) {
|
||||
return passwords.get(id);
|
||||
}
|
||||
|
||||
if (strategy == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var pass = strategy.retrieve(prompt, id);
|
||||
if (pass == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
passwords.put(id, pass);
|
||||
return pass;
|
||||
}
|
||||
|
||||
public static void clear(UUID id) {
|
||||
passwords.remove(id);
|
||||
}
|
||||
|
||||
public static void set(UUID id, SecretValue value) {
|
||||
passwords.put(id, value);
|
||||
}
|
||||
|
||||
public static Optional<SecretValue> get(UUID id) {
|
||||
return Optional.ofNullable(passwords.get(id));
|
||||
}
|
||||
}
|
72
app/src/main/java/io/xpipe/app/util/SecretManager.java
Normal file
72
app/src/main/java/io/xpipe/app/util/SecretManager.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
package io.xpipe.app.util;
|
||||
|
||||
import io.xpipe.core.util.SecretValue;
|
||||
import io.xpipe.core.util.UuidHelper;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class SecretManager {
|
||||
|
||||
@Value
|
||||
@AllArgsConstructor
|
||||
public static class SecretReference {
|
||||
|
||||
UUID secretId;
|
||||
int subId;
|
||||
|
||||
public SecretReference(Object store) {
|
||||
this.secretId = UuidHelper.generateFromObject(store);
|
||||
this.subId = 0;
|
||||
}
|
||||
|
||||
public SecretReference(Object store, int sub) {
|
||||
this.secretId = UuidHelper.generateFromObject(store);
|
||||
this.subId = sub;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<SecretReference, SecretValue> passwords = new HashMap<>();
|
||||
|
||||
public static SecretValue retrieve(SecretRetrievalStrategy strategy, String prompt, Object key) throws Exception {
|
||||
return retrieve(strategy, prompt,key, 0);
|
||||
}
|
||||
public static SecretValue retrieve(SecretRetrievalStrategy strategy, String prompt, Object key, int sub) throws Exception {
|
||||
var ref = new SecretReference(key, sub);
|
||||
if (strategy == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (strategy.shouldCache() && passwords.containsKey(ref)) {
|
||||
return passwords.get(ref);
|
||||
}
|
||||
|
||||
var pass = strategy.retrieve(prompt, ref.getSecretId(), ref.getSubId());
|
||||
if (pass == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (strategy.shouldCache()) {
|
||||
passwords.put(ref, pass);
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
|
||||
public static void clearAll(Object store) {
|
||||
var id = UuidHelper.generateFromObject(store);
|
||||
passwords.entrySet().removeIf(secretReferenceSecretValueEntry -> secretReferenceSecretValueEntry.getKey().getSecretId().equals(id));
|
||||
}
|
||||
|
||||
public static void clear(SecretReference ref) {
|
||||
passwords.remove(ref);
|
||||
}
|
||||
|
||||
public static void set(SecretReference ref, SecretValue value) {
|
||||
passwords.put(ref, value);
|
||||
}
|
||||
|
||||
public static Optional<SecretValue> get(SecretReference ref) {
|
||||
return Optional.ofNullable(passwords.get(ref));
|
||||
}
|
||||
}
|
|
@ -26,15 +26,17 @@ import java.util.function.Supplier;
|
|||
})
|
||||
public interface SecretRetrievalStrategy {
|
||||
|
||||
SecretValue retrieve(String displayName, UUID id) throws Exception;
|
||||
SecretValue retrieve(String displayName, UUID id, int sub) throws Exception;
|
||||
|
||||
boolean isLocalAskpassCompatible();
|
||||
|
||||
boolean shouldCache();
|
||||
|
||||
@JsonTypeName("none")
|
||||
public static class None implements SecretRetrievalStrategy {
|
||||
|
||||
@Override
|
||||
public SecretValue retrieve(String displayName, UUID id) {
|
||||
public SecretValue retrieve(String displayName, UUID id, int sub) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -42,6 +44,11 @@ public interface SecretRetrievalStrategy {
|
|||
public boolean isLocalAskpassCompatible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCache() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@JsonTypeName("reference")
|
||||
|
@ -55,7 +62,7 @@ public interface SecretRetrievalStrategy {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SecretValue retrieve(String displayName, UUID id) {
|
||||
public SecretValue retrieve(String displayName, UUID id, int sub) {
|
||||
return supplier.get();
|
||||
}
|
||||
|
||||
|
@ -63,6 +70,11 @@ public interface SecretRetrievalStrategy {
|
|||
public boolean isLocalAskpassCompatible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCache() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@JsonTypeName("inPlace")
|
||||
|
@ -79,10 +91,14 @@ public interface SecretRetrievalStrategy {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SecretValue retrieve(String displayName, UUID id) {
|
||||
public SecretValue retrieve(String displayName, UUID id, int sub) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCache() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isLocalAskpassCompatible() {
|
||||
return false;
|
||||
|
@ -93,10 +109,14 @@ public interface SecretRetrievalStrategy {
|
|||
public static class Prompt implements SecretRetrievalStrategy {
|
||||
|
||||
@Override
|
||||
public SecretValue retrieve(String displayName, UUID id) {
|
||||
return AskpassAlert.query(displayName, UUID.randomUUID(), id);
|
||||
public SecretValue retrieve(String displayName, UUID id, int sub) {
|
||||
return AskpassAlert.query(displayName, UUID.randomUUID(), id, sub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCache() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean isLocalAskpassCompatible() {
|
||||
return true;
|
||||
|
@ -112,7 +132,7 @@ public interface SecretRetrievalStrategy {
|
|||
String key;
|
||||
|
||||
@Override
|
||||
public SecretValue retrieve(String displayName, UUID id) throws Exception {
|
||||
public SecretValue retrieve(String displayName, UUID id, int sub) throws Exception {
|
||||
var cmd = AppPrefs.get().passwordManagerString(key);
|
||||
if (cmd == null) {
|
||||
return null;
|
||||
|
@ -123,6 +143,11 @@ public interface SecretRetrievalStrategy {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCache() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocalAskpassCompatible() {
|
||||
return false;
|
||||
|
@ -138,12 +163,17 @@ public interface SecretRetrievalStrategy {
|
|||
String command;
|
||||
|
||||
@Override
|
||||
public SecretValue retrieve(String displayName, UUID id) throws Exception {
|
||||
public SecretValue retrieve(String displayName, UUID id, int sub) throws Exception {
|
||||
try (var cc = new LocalStore().createBasicControl().command(command).start()) {
|
||||
return SecretHelper.encrypt(cc.readStdoutOrThrow());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCache() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocalAskpassCompatible() {
|
||||
return false;
|
||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 59 KiB |
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="50.4mm" height="54.4mm" inkscape:version="1.0.2 (e86c870879, 2021-01-15, custom)" sodipodi:docname="Endeavouros_Logo.svg" version="1.1" viewBox="0 0 50.4 54.4" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd">
|
||||
<sodipodi:namedview id="cvfa" bordercolor="#666666" borderopacity="1.0" inkscape:current-layer="g1230-2" inkscape:cx="196.53533" inkscape:cy="181.7514" inkscape:document-rotation="0" inkscape:document-units="mm" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:window-height="1014" inkscape:window-maximized="1" inkscape:window-width="1920" inkscape:window-x="0" inkscape:window-y="36" inkscape:zoom="1.743335" pagecolor="#ffffff" showgrid="false"/>
|
||||
<title>EndeavourOS Logo</title>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g transform="translate(-66.5 -122)" inkscape:groupmode="layer" inkscape:label="Layer 1">
|
||||
<g transform="translate(76.2 -12.7)">
|
||||
<g transform="matrix(1.47 0 0 1.47 -519 105)">
|
||||
<g transform="matrix(.963 0 0 .983 13.5 .76)">
|
||||
<g transform="matrix(.678 0 0 .678 452 49.2)">
|
||||
<path d="m-127-42.3c4.57 6.45 23.8 31.4 10.7 36.6-6.12 2.81-34-1.65-33.6-0.921-2 3.28-3.59 5.92-3.59 5.92s21.5 0.967 38.1-1.27c23.7-3.18-4.88-33.5-11.6-40.3z" style="fill:#7f7fff;stroke-width:.585" inkscape:connector-curvature="0"/>
|
||||
<path d="m-127-42.3c-1.52 0.209-29.4 34.5-29.4 34.5s2.01 0.57 6.58 1.23c1.48-1.15 22.3-36.2 22.9-35.7-0.0107-0.0141-0.028-0.0193-0.0522-0.016z" style="fill:#ff7f7f;stroke-width:.585" inkscape:connector-curvature="0"/>
|
||||
<path d="m-127-42.3c-0.96-0.156-22.9 35.7-22.9 35.7s19.9 2.1 28.1 1.96c23.1-0.39 0.176-30.6-5.16-37.7-7e-3 -7e-3 -0.0151-0.0108-0.0248-0.0124z" style="fill:#7f3fbf;stroke-width:.585" inkscape:connector-curvature="0"/>
|
||||
</g>
|
||||
<path transform="matrix(.179 0 0 .179 345 18.5)" d="m116 183c-2.54 0-4.6 2.05-4.6 4.55v24.1c0.0501 2.46 2.1 4.5 4.6 4.5h2.49c2.44-0.102 4.39-2.05 4.44-4.5v-24.1c0-2.46-2-4.45-4.44-4.55h-0.0117zm-107 0.314c-0.818 0-1.48 0.638-1.54 1.41l-0.00195 0.0254v31.1h7.74c1.2 0 1.93-0.586 2.24-1.14l0.0059-0.0117 0.0059-0.01c0.179-0.359 0.689-1.56 1.04-2.36l0.35-0.789h-7.04v-10.3c0-0.0711 0.131-0.203 0.203-0.203h1.35c1.2 0 1.9-0.613 2.2-1.14l0.0059-0.0117 0.0059-0.01c0.0958-0.191 0.249-0.559 0.445-1.02 0.196-0.46 0.421-0.986 0.598-1.38l0.35-0.789h-5.15v-8.78c0-0.186 0.0165-0.203 0.203-0.203h2.6c1.21 0 1.95-0.631 2.22-1.23l1.44-3.12zm15 0v32.5h4.35v-13l2.35 10.6c0.0657 0.307 0.172 0.902 0.561 1.45 0.39 0.549 1.12 1.01 2.14 1.01h2.04v-32.5h-4.35v13.1l-2.21-10.9v-2e-3c-0.0953-0.477-0.241-1.05-0.693-1.5-0.453-0.453-1.16-0.701-2.15-0.701zm18.1 0v32.5h6.8c2.5 0 4.5-2.01 4.55-4.5v-23.5c-0.0501-2.49-2.06-4.5-4.55-4.5zm21.1 0c-0.818 0-1.48 0.637-1.55 1.41l-2e-3 0.0254v31.1h7.74c1.2 0 1.93-0.586 2.24-1.14l0.0059-0.0117 0.0059-0.01c0.179-0.358 0.689-1.56 1.04-2.36l0.35-0.789h-7.04v-10.3c0-0.073 0.13-0.203 0.201-0.203h1.35c1.2 0 1.9-0.614 2.2-1.14l0.0059-0.0117 0.0059-0.01c0.0953-0.19 0.251-0.559 0.447-1.02 0.197-0.46 0.421-0.986 0.598-1.38l0.35-0.789h-5.15v-8.78c0-0.188 0.0168-0.203 0.201-0.203h2.6c1.21 0 1.95-0.625 2.22-1.22l2e-3 -4e-3 1.44-3.12zm17.9 0-0.0723 0.477-4.86 32.1h4.69l2.34-17.9 2.34 17.9h4.69l-4.63-30.4v-2e-3c-0.0702-0.445-0.159-0.964-0.504-1.42-0.345-0.458-0.964-0.756-1.76-0.756zm11.7 0 0.0996 0.646 4.49 29.2v4e-3c0.0167 0.101 0.104 0.75 0.436 1.37 0.332 0.623 1.02 1.29 2.05 1.29h2.1l4.97-32.5h-4.37l-2.71 17.8-2.45-16.1-2e-3 -6e-3c-0.211-1.21-0.974-1.68-1.5-1.68zm38.7 0c-0.799 0-1.43 0.638-1.5 1.41l-2e-3 0.0254v26.9c0 2.5 2.07 4.42 4.55 4.42h3.03v-0.16c2.13-0.31 3.86-2 3.86-4.26v-28.3h-4.35v27.7c0 0.639-0.506 1.14-1.15 1.14h-0.492c-0.64 0-1.1-0.488-1.1-1.14v-27.7zm16.7 0v32.5h4.35v-13.5h1.15c0.318 0 0.566 0.084 0.75 0.271 0.184 0.187 0.35 0.525 0.35 1.19v12.1h4.35v-12.6s0.0279-0.642-0.123-1.38c-0.107-0.525-0.385-1.09-0.807-1.57 0.125-0.12 0.325-0.173 0.41-0.311 0.224-0.362 0.342-0.759 0.414-1.13 0.145-0.74 0.105-1.41 0.105-1.41v-9.66c0-2.51-2.05-4.51-4.51-4.51zm-30.8 3.63h0.467c0.64 0 1.14 0.491 1.14 1.19v22.9c0 0.699-0.505 1.19-1.14 1.19h-0.467c-0.655-0.0312-1.17-0.549-1.17-1.19v-22.9c0-0.64 0.516-1.16 1.17-1.19zm35.2 0.492h1.15c0.328 0 0.609 0.0895 0.789 0.24 0.18 0.151 0.311 0.362 0.311 0.816v8.44c0 0.613-0.151 0.867-0.318 1.01-0.167 0.146-0.434 0.223-0.781 0.223h-1.15zm-106 0.225h1.55c0.355 0 0.65 0.0931 0.834 0.244 0.184 0.151 0.312 0.359 0.312 0.812v21.7c0 0.481-0.133 0.7-0.316 0.854-0.183 0.153-0.475 0.246-0.83 0.246h-1.55z" style="color-rendering:auto;color:#000000;dominant-baseline:auto;fill:#280b0b;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;image-rendering:auto;isolation:auto;mix-blend-mode:normal;shape-padding:0;shape-rendering:auto;solid-color:#000000;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
|
||||
<path transform="matrix(.179 0 0 .179 345 18.5)" d="m169 183c-2.54 0-4.6 2.05-4.6 4.55v24.1c0.0501 2.46 2.1 4.5 4.6 4.5h2.49c2.44-0.102 4.39-2.05 4.44-4.5v-24.1c0-2.46-2-4.45-4.44-4.55h-0.0117zm18.3 0c-2.57 0-4.6 2.23-4.6 4.73v3.2s-0.128 2.3 1.51 5.29l3.86 7.23 4e-3 8e-3s0.33 0.577 0.664 1.38c0.334 0.802 0.654 1.83 0.654 2.61v3.59c0 0.698-0.506 1.19-1.15 1.19-0.64 0-1.14-0.504-1.14-1.14v-6.34l-0.789 0.35c-0.405 0.18-0.931 0.416-1.39 0.617-0.457 0.201-0.894 0.381-0.939 0.396l-0.0508 0.0176-0.043 0.0274c-0.539 0.3-1.19 1.03-1.19 2.24v3.24c0.0501 2.44 2 4.44 4.44 4.54h2.04c2.54 0 4.6-2.05 4.6-4.55v-3.96s0.129-2.3-1.5-5.29l-3.86-7.28-4e-3 -0.01s-0.329-0.563-0.662-1.35c-0.333-0.79-0.654-1.8-0.654-2.58v-3.01c0-0.699 0.507-1.19 1.15-1.19 0.64 0 1.15 0.491 1.15 1.19v4.48l0.775-0.328c0.871-0.367 2.1-0.934 2.41-1.09l0.0117-8e-3 0.0117-6e-3c0.54-0.3 1.18-1.03 1.18-2.24v-1.21c0-2.46-1.96-4.68-4.45-4.73h-6e-3zm-17.4 3.95h0.467c0.64 0 1.14 0.491 1.14 1.19v22.9c0 0.699-0.505 1.19-1.14 1.19h-0.467c-0.656-0.0312-1.17-0.549-1.17-1.19v-22.9c0-0.64 0.516-1.16 1.17-1.19z" style="fill:#7f7fff;font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.5 KiB |
|
@ -40,6 +40,13 @@ dragFiles=Drag files within browser
|
|||
dragLocalFiles=Drag local files from here
|
||||
null=$VALUE$ must be not null
|
||||
roots=Roots
|
||||
terminator=Terminator
|
||||
kitty=Kitty
|
||||
terminology=Terminology
|
||||
coolRetroTerm=Cool Retro Term
|
||||
guake=Guake
|
||||
alacritty=Alacritty
|
||||
tilda=Tilda
|
||||
recent=Recent
|
||||
hostFeatureUnsupported=$FEATURE$ is not installed on the host
|
||||
missingStore=$NAME$ does not exist
|
||||
|
|
|
@ -21,7 +21,9 @@ public class AskpassExchange implements MessageExchange {
|
|||
@Value
|
||||
public static class Request implements RequestMessage {
|
||||
@NonNull
|
||||
UUID id;
|
||||
UUID storeId;
|
||||
|
||||
int subId;
|
||||
|
||||
@NonNull
|
||||
UUID request;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package io.xpipe.core.process;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
public class ElevationConfig {
|
||||
|
||||
boolean requiresPassword;
|
||||
}
|
|
@ -28,6 +28,8 @@ public interface ShellControl extends ProcessControl {
|
|||
|
||||
ShellControl onExit(Consumer<ShellControl> pc);
|
||||
|
||||
ShellControl onFail(Consumer<Throwable> t);
|
||||
ElevationResult elevateCommand(String input) throws Exception;
|
||||
ShellControl withExceptionConverter(ExceptionConverter converter);
|
||||
|
||||
ShellControl withErrorFormatter(Function<String, String> formatter);
|
||||
|
@ -90,12 +92,14 @@ public interface ShellControl extends ProcessControl {
|
|||
}
|
||||
}
|
||||
|
||||
ElevationResult elevateCommand(String input) throws Exception;
|
||||
ElevationResult buildElevatedCommand(String input) throws Exception;
|
||||
|
||||
void restart() throws Exception;
|
||||
|
||||
OsType getOsType();
|
||||
|
||||
ElevationConfig getElevationConfig();
|
||||
|
||||
ShellControl elevated(String message, FailableFunction<ShellControl, Boolean, Exception> elevationFunction);
|
||||
|
||||
default ShellControl elevationPassword(SecretValue value) {
|
||||
|
|
|
@ -17,13 +17,6 @@ createShortcut=Create desktop shortcut
|
|||
browseFiles=Browse Files
|
||||
targetPath=Target path
|
||||
newDirectory=New directory
|
||||
terminator=Terminator
|
||||
kitty=Kitty
|
||||
terminology=Terminology
|
||||
coolRetroTerm=Cool Retro Term
|
||||
guake=Guake
|
||||
alacritty=Alacritty
|
||||
tilda=Tilda
|
||||
copyShareLink=Copy share link
|
||||
selectStore=Select Store
|
||||
saveSource=Save for later
|
||||
|
|
Loading…
Reference in a new issue