diff --git a/Makefile b/Makefile
index 0e8fed1..b16aa4f 100644
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ ifneq ($(strip $(SIGNPASS)),)
GOGIO_SIGN_FLAGS += -signpass $(SIGNPASS)
endif
-.PHONY: apk archlinux-pkgbuild
+.PHONY: apk archlinux-pkgbuild browser-bridge
apk: android/keepassgo-android.jar
@test -x "$(JAVA_HOME)/bin/java" || { echo "JAVA_HOME must point to a working JDK install"; exit 1; }
@test -d "$(ANDROID_SDK_ROOT)" || { echo "ANDROID_SDK_ROOT must point to an Android SDK install"; exit 1; }
@@ -68,3 +68,6 @@ archlinux-pkgbuild: $(ARCH_PKG_TMPL) Makefile
-e 's|@PKGVER@|$(ARCH_PKGVER)|g' \
-e 's|@REPO_DIR@|$(ARCH_REPO_DIR)|g' \
"$(ARCH_PKG_TMPL)" > "$(ARCH_PKGBUILD)"
+
+browser-bridge:
+ go build ./cmd/keepassgo-browser-bridge
diff --git a/README.md b/README.md
index 8118850..19fe7c0 100644
--- a/README.md
+++ b/README.md
@@ -63,6 +63,7 @@ makepkg -si
The package installs:
- `/usr/bin/keepassgo`
+- `/usr/bin/keepassgo-browser-bridge`
- a desktop entry at `/usr/share/applications/keepassgo.desktop`
- application icons under the hicolor theme
@@ -98,3 +99,8 @@ You will need the Android SDK and NDK installed and configured for real device o
Desktop automation is resolved through the secure gRPC API rather than synthetic auto-type.
See [`docs/desktop-automation.md`](./docs/desktop-automation.md).
+
+## Browser Extension
+
+Firefox and Chromium browser integration is available through the local gRPC API plus a native messaging bridge.
+See [`docs/browser-extension.md`](./docs/browser-extension.md).
diff --git a/browser/extension/README.md b/browser/extension/README.md
new file mode 100644
index 0000000..fbd3f03
--- /dev/null
+++ b/browser/extension/README.md
@@ -0,0 +1,11 @@
+# KeePassGO Browser Extension
+
+Shared extension assets for Firefox and Chromium-based browsers live here.
+
+- `manifest.firefox.json` uses the fixed Firefox extension id `browser@keepassgo.invalid`
+- `manifest.chromium.json` is the Chromium/Chrome manifest template
+- `background.js` talks to the native messaging host `org.keepassgo.browser`
+- `content.js` fills username and password fields on the current page
+- `options.html` stores the local gRPC address and API token in browser extension storage
+
+The extension sends the API token to the native host on each request. The bridge does not store the token on disk.
diff --git a/browser/extension/background.js b/browser/extension/background.js
new file mode 100644
index 0000000..07e0a76
--- /dev/null
+++ b/browser/extension/background.js
@@ -0,0 +1,195 @@
+const ext = globalThis.browser ?? globalThis.chrome;
+const nativeHost = "org.keepassgo.browser";
+const defaultSettings = {
+ grpcAddress: "127.0.0.1:47777",
+ bearerToken: ""
+};
+
+function storageGet(keys) {
+ return new Promise((resolve, reject) => {
+ ext.storage.local.get(keys, (value) => {
+ const error = ext.runtime.lastError;
+ if (error) {
+ reject(new Error(error.message));
+ return;
+ }
+ resolve(value);
+ });
+ });
+}
+
+function storageSet(value) {
+ return new Promise((resolve, reject) => {
+ ext.storage.local.set(value, () => {
+ const error = ext.runtime.lastError;
+ if (error) {
+ reject(new Error(error.message));
+ return;
+ }
+ resolve();
+ });
+ });
+}
+
+function tabsQuery(query) {
+ return new Promise((resolve, reject) => {
+ ext.tabs.query(query, (tabs) => {
+ const error = ext.runtime.lastError;
+ if (error) {
+ reject(new Error(error.message));
+ return;
+ }
+ resolve(tabs);
+ });
+ });
+}
+
+function tabsSendMessage(tabId, message) {
+ return new Promise((resolve, reject) => {
+ ext.tabs.sendMessage(tabId, message, (response) => {
+ const error = ext.runtime.lastError;
+ if (error) {
+ reject(new Error(error.message));
+ return;
+ }
+ resolve(response);
+ });
+ });
+}
+
+function connectNative(message) {
+ return new Promise((resolve, reject) => {
+ ext.runtime.sendNativeMessage(nativeHost, message, (response) => {
+ const error = ext.runtime.lastError;
+ if (error) {
+ reject(new Error(error.message));
+ return;
+ }
+ resolve(response);
+ });
+ });
+}
+
+async function loadSettings() {
+ const stored = await storageGet(["grpcAddress", "bearerToken"]);
+ return {
+ grpcAddress: (stored.grpcAddress || defaultSettings.grpcAddress).trim(),
+ bearerToken: (stored.bearerToken || "").trim()
+ };
+}
+
+async function activePageContext() {
+ const [tab] = await tabsQuery({ active: true, currentWindow: true });
+ return {
+ tabId: tab?.id ?? null,
+ url: typeof tab?.url === "string" ? tab.url : ""
+ };
+}
+
+async function statusForPage() {
+ const settings = await loadSettings();
+ const page = await activePageContext();
+ if (!settings.bearerToken) {
+ return {
+ success: false,
+ configured: false,
+ status: null,
+ pageUrl: page.url,
+ matches: [],
+ error: "Set an API token in extension settings."
+ };
+ }
+
+ const status = await connectNative({
+ action: "status",
+ grpcAddress: settings.grpcAddress,
+ bearerToken: settings.bearerToken
+ });
+ if (!status.success || status.status?.locked || !page.url.startsWith("http")) {
+ return {
+ success: status.success,
+ configured: true,
+ status: status.status ?? null,
+ pageUrl: page.url,
+ matches: [],
+ error: status.error ?? ""
+ };
+ }
+
+ const matches = await connectNative({
+ action: "find-logins",
+ grpcAddress: settings.grpcAddress,
+ bearerToken: settings.bearerToken,
+ url: page.url
+ });
+ return {
+ success: matches.success,
+ configured: true,
+ status: matches.status ?? status.status ?? null,
+ pageUrl: page.url,
+ matches: matches.matches ?? [],
+ error: matches.error ?? ""
+ };
+}
+
+async function fillLogin(entryId) {
+ const settings = await loadSettings();
+ const page = await activePageContext();
+ if (!settings.bearerToken) {
+ throw new Error("API token is not configured.");
+ }
+ if (page.tabId == null) {
+ throw new Error("No active tab is available.");
+ }
+
+ const response = await connectNative({
+ action: "get-login",
+ grpcAddress: settings.grpcAddress,
+ bearerToken: settings.bearerToken,
+ entryId,
+ url: page.url
+ });
+ if (!response.success || !response.credential) {
+ throw new Error(response.error || "KeePassGO did not return a credential.");
+ }
+
+ const fillResponse = await tabsSendMessage(page.tabId, {
+ type: "keepassgo-fill-credential",
+ credential: response.credential
+ });
+ if (!fillResponse?.ok) {
+ throw new Error(fillResponse?.error || "The current page could not be filled.");
+ }
+ return {
+ credential: response.credential,
+ pageUrl: page.url
+ };
+}
+
+ext.runtime.onMessage.addListener((message, _sender, sendResponse) => {
+ (async () => {
+ switch (message?.type) {
+ case "keepassgo-popup-state":
+ sendResponse(await statusForPage());
+ return;
+ case "keepassgo-fill-entry":
+ sendResponse({ success: true, ...(await fillLogin(message.entryId)) });
+ return;
+ case "keepassgo-load-settings":
+ sendResponse({ success: true, settings: await loadSettings() });
+ return;
+ case "keepassgo-save-settings":
+ await storageSet({
+ grpcAddress: String(message.settings?.grpcAddress || defaultSettings.grpcAddress).trim(),
+ bearerToken: String(message.settings?.bearerToken || "").trim()
+ });
+ sendResponse({ success: true });
+ return;
+ default:
+ sendResponse({ success: false, error: `Unsupported message ${message?.type || ""}`.trim() });
+ }
+ })().catch((error) => {
+ sendResponse({ success: false, error: error instanceof Error ? error.message : String(error) });
+ });
+ return true;
+});
diff --git a/browser/extension/content.js b/browser/extension/content.js
new file mode 100644
index 0000000..3680808
--- /dev/null
+++ b/browser/extension/content.js
@@ -0,0 +1,69 @@
+function isVisibleInput(input) {
+ if (!(input instanceof HTMLInputElement)) {
+ return false;
+ }
+ if (input.disabled || input.readOnly) {
+ return false;
+ }
+ const style = window.getComputedStyle(input);
+ if (style.display === "none" || style.visibility === "hidden") {
+ return false;
+ }
+ return input.offsetParent !== null || style.position === "fixed";
+}
+
+function dispatchFillEvents(input) {
+ input.dispatchEvent(new Event("input", { bubbles: true }));
+ input.dispatchEvent(new Event("change", { bubbles: true }));
+}
+
+function findPasswordInput() {
+ return Array.from(document.querySelectorAll('input[type="password"]')).find(isVisibleInput) || null;
+}
+
+function findUsernameInput(passwordInput) {
+ const form = passwordInput?.form || null;
+ const scope = form || document;
+ const candidates = Array.from(scope.querySelectorAll('input[type="text"], input[type="email"], input:not([type])'))
+ .filter(isVisibleInput);
+ if (passwordInput) {
+ const sameForm = candidates.find((input) => input.form === passwordInput.form);
+ if (sameForm) {
+ return sameForm;
+ }
+ }
+ return candidates[0] || null;
+}
+
+function fillCredential(credential) {
+ const passwordInput = findPasswordInput();
+ const usernameInput = findUsernameInput(passwordInput);
+
+ if (usernameInput && credential.username) {
+ usernameInput.focus();
+ usernameInput.value = credential.username;
+ dispatchFillEvents(usernameInput);
+ }
+ if (passwordInput && credential.password) {
+ passwordInput.focus();
+ passwordInput.value = credential.password;
+ dispatchFillEvents(passwordInput);
+ }
+
+ if (!usernameInput && !passwordInput) {
+ return { ok: false, error: "No fillable username or password fields were found." };
+ }
+ return { ok: true };
+}
+
+(globalThis.browser ?? globalThis.chrome).runtime.onMessage.addListener((message, _sender, sendResponse) => {
+ if (message?.type !== "keepassgo-fill-credential") {
+ return false;
+ }
+ try {
+ sendResponse(fillCredential(message.credential || {}));
+ } catch (error) {
+ sendResponse({ ok: false, error: error instanceof Error ? error.message : String(error) });
+ }
+ return false;
+});
diff --git a/browser/extension/manifest.chromium.json b/browser/extension/manifest.chromium.json
new file mode 100644
index 0000000..77b3c68
--- /dev/null
+++ b/browser/extension/manifest.chromium.json
@@ -0,0 +1,26 @@
+{
+ "manifest_version": 3,
+ "name": "KeePassGO Browser",
+ "version": "0.1.0",
+ "description": "Fill credentials from KeePassGO over the local gRPC API.",
+ "permissions": ["activeTab", "nativeMessaging", "storage", "tabs"],
+ "host_permissions": ["http://*/*", "https://*/*"],
+ "background": {
+ "service_worker": "background.js"
+ },
+ "action": {
+ "default_title": "KeePassGO Browser",
+ "default_popup": "popup.html"
+ },
+ "options_ui": {
+ "page": "options.html",
+ "open_in_tab": true
+ },
+ "content_scripts": [
+ {
+ "matches": ["http://*/*", "https://*/*"],
+ "js": ["content.js"],
+ "run_at": "document_idle"
+ }
+ ]
+}
diff --git a/browser/extension/manifest.firefox.json b/browser/extension/manifest.firefox.json
new file mode 100644
index 0000000..ea23659
--- /dev/null
+++ b/browser/extension/manifest.firefox.json
@@ -0,0 +1,31 @@
+{
+ "manifest_version": 3,
+ "name": "KeePassGO Browser",
+ "version": "0.1.0",
+ "description": "Fill credentials from KeePassGO over the local gRPC API.",
+ "permissions": ["activeTab", "nativeMessaging", "storage", "tabs"],
+ "host_permissions": ["http://*/*", "https://*/*"],
+ "background": {
+ "service_worker": "background.js"
+ },
+ "action": {
+ "default_title": "KeePassGO Browser",
+ "default_popup": "popup.html"
+ },
+ "options_ui": {
+ "page": "options.html",
+ "open_in_tab": true
+ },
+ "content_scripts": [
+ {
+ "matches": ["http://*/*", "https://*/*"],
+ "js": ["content.js"],
+ "run_at": "document_idle"
+ }
+ ],
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "browser@keepassgo.invalid"
+ }
+ }
+}
diff --git a/browser/extension/options.html b/browser/extension/options.html
new file mode 100644
index 0000000..a1f1246
--- /dev/null
+++ b/browser/extension/options.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+ KeePassGO Browser Settings
+
+
+
+
+
+
+
+
+
+
diff --git a/browser/extension/options.js b/browser/extension/options.js
new file mode 100644
index 0000000..75eeee3
--- /dev/null
+++ b/browser/extension/options.js
@@ -0,0 +1,47 @@
+const extOptions = globalThis.browser ?? globalThis.chrome;
+
+function runtimeSend(message) {
+ return new Promise((resolve, reject) => {
+ extOptions.runtime.sendMessage(message, (response) => {
+ const error = extOptions.runtime.lastError;
+ if (error) {
+ reject(new Error(error.message));
+ return;
+ }
+ resolve(response);
+ });
+ });
+}
+
+async function loadSettings() {
+ const response = await runtimeSend({ type: "keepassgo-load-settings" });
+ if (!response?.success) {
+ throw new Error(response?.error || "Could not load settings.");
+ }
+ document.getElementById("grpc-address").value = response.settings.grpcAddress || "127.0.0.1:47777";
+ document.getElementById("bearer-token").value = response.settings.bearerToken || "";
+}
+
+async function saveSettings(event) {
+ event.preventDefault();
+ const status = document.getElementById("settings-status");
+ status.textContent = "Saving…";
+ try {
+ const response = await runtimeSend({
+ type: "keepassgo-save-settings",
+ settings: {
+ grpcAddress: document.getElementById("grpc-address").value,
+ bearerToken: document.getElementById("bearer-token").value
+ }
+ });
+ if (!response?.success) {
+ throw new Error(response?.error || "Could not save settings.");
+ }
+ status.textContent = "Saved.";
+ } catch (error) {
+ status.textContent = error instanceof Error ? error.message : String(error);
+ }
+}
+
+document.getElementById("settings-form").addEventListener("submit", saveSettings);
+void loadSettings();
diff --git a/browser/extension/popup.html b/browser/extension/popup.html
new file mode 100644
index 0000000..b5a6c2c
--- /dev/null
+++ b/browser/extension/popup.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+ KeePassGO Browser
+
+
+
+
+
+
+
KeePassGO
+
Checking current page
+
+ Settings
+
+
+ Loading
+ Checking KeePassGO.
+
+
+
+
+
+
diff --git a/browser/extension/popup.js b/browser/extension/popup.js
new file mode 100644
index 0000000..b6bd51e
--- /dev/null
+++ b/browser/extension/popup.js
@@ -0,0 +1,101 @@
+const extPopup = globalThis.browser ?? globalThis.chrome;
+
+function runtimeSend(message) {
+ return new Promise((resolve, reject) => {
+ extPopup.runtime.sendMessage(message, (response) => {
+ const error = extPopup.runtime.lastError;
+ if (error) {
+ reject(new Error(error.message));
+ return;
+ }
+ resolve(response);
+ });
+ });
+}
+
+function hostFromURL(rawURL) {
+ try {
+ return new URL(rawURL).host || rawURL;
+ } catch (_error) {
+ return rawURL || "Current page";
+ }
+}
+
+function setStatus(title, message, tone) {
+ const card = document.getElementById("status-card");
+ card.dataset.tone = tone || "neutral";
+ document.getElementById("status-title").textContent = title;
+ document.getElementById("status-message").textContent = message;
+}
+
+function renderMatches(state) {
+ const root = document.getElementById("matches");
+ root.textContent = "";
+ if (!Array.isArray(state.matches) || state.matches.length === 0) {
+ const empty = document.createElement("p");
+ empty.className = "subtle";
+ empty.textContent = "No matching entries for this page.";
+ root.appendChild(empty);
+ return;
+ }
+
+ for (const match of state.matches) {
+ const row = document.createElement("button");
+ row.type = "button";
+ row.className = "match-row";
+ row.innerHTML = `
+
+ ${match.title}
+ ${match.username || "No username"}
+
+ ${match.quality || ""}
+ `;
+ row.addEventListener("click", async () => {
+ row.disabled = true;
+ try {
+ const result = await runtimeSend({ type: "keepassgo-fill-entry", entryId: match.id });
+ if (!result?.success) {
+ throw new Error(result?.error || "Fill failed.");
+ }
+ setStatus("Filled", `${match.title} was sent to the current page.`, "ready");
+ } catch (error) {
+ setStatus("Fill failed", error instanceof Error ? error.message : String(error), "error");
+ } finally {
+ row.disabled = false;
+ }
+ });
+ root.appendChild(row);
+ }
+}
+
+async function main() {
+ try {
+ const state = await runtimeSend({ type: "keepassgo-popup-state" });
+ document.getElementById("page-host").textContent = hostFromURL(state.pageUrl || "");
+
+ if (!state.configured) {
+ setStatus("Configure access", state.error || "Set the API token in extension settings.", "warning");
+ renderMatches({ matches: [] });
+ return;
+ }
+ if (!state.success) {
+ setStatus("KeePassGO unavailable", state.error || "The native host could not reach KeePassGO.", "error");
+ renderMatches({ matches: [] });
+ return;
+ }
+ if (state.status?.locked) {
+ setStatus("Vault locked", "Unlock KeePassGO, then open the popup again.", "warning");
+ renderMatches({ matches: [] });
+ return;
+ }
+
+ const count = Array.isArray(state.matches) ? state.matches.length : 0;
+ setStatus("Ready", count === 0 ? "KeePassGO is connected." : `${count} matching entr${count === 1 ? "y" : "ies"} found.`, "ready");
+ renderMatches(state);
+ } catch (error) {
+ setStatus("Error", error instanceof Error ? error.message : String(error), "error");
+ renderMatches({ matches: [] });
+ }
+}
+
+void main();
diff --git a/browser/extension/style.css b/browser/extension/style.css
new file mode 100644
index 0000000..3fc7536
--- /dev/null
+++ b/browser/extension/style.css
@@ -0,0 +1,174 @@
+:root {
+ color-scheme: light;
+ --ink: #214f44;
+ --ink-soft: #4d6d66;
+ --surface: #fffdfa;
+ --surface-2: #f2f7f3;
+ --line: #d7e3dc;
+ --accent: #255f4a;
+ --accent-soft: #dfeee6;
+ --warn: #9f5f0e;
+ --error: #9f2f2f;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+ font: 14px/1.4 "Noto Sans", "Liberation Sans", sans-serif;
+ color: var(--ink);
+ background:
+ radial-gradient(circle at top right, #ecf5ef, transparent 38%),
+ linear-gradient(180deg, #f8fbf8, #eef4f0);
+}
+
+body.popup {
+ min-width: 360px;
+}
+
+.surface {
+ padding: 16px;
+}
+
+.topbar {
+ display: flex;
+ align-items: start;
+ justify-content: space-between;
+ gap: 12px;
+ margin-bottom: 16px;
+}
+
+h1,
+h2,
+p {
+ margin: 0;
+}
+
+h1 {
+ font-size: 22px;
+ line-height: 1.1;
+}
+
+h2 {
+ font-size: 14px;
+ text-transform: uppercase;
+ letter-spacing: 0.08em;
+ margin-bottom: 8px;
+ color: var(--ink-soft);
+}
+
+.subtle {
+ color: var(--ink-soft);
+}
+
+.status-card {
+ padding: 12px 14px;
+ border-radius: 12px;
+ border: 1px solid var(--line);
+ background: var(--surface);
+ margin-bottom: 16px;
+}
+
+.status-card[data-tone="ready"] {
+ border-color: #c5dccf;
+ background: var(--accent-soft);
+}
+
+.status-card[data-tone="warning"] {
+ border-color: #e4d0ae;
+ background: #fbf4e7;
+}
+
+.status-card[data-tone="error"] {
+ border-color: #e4bcbc;
+ background: #fcf1f1;
+}
+
+.match-list {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.match-row,
+button,
+.link-button {
+ appearance: none;
+ border: 0;
+ border-radius: 12px;
+ background: var(--surface);
+ color: var(--ink);
+ text-decoration: none;
+}
+
+.match-row {
+ display: flex;
+ width: 100%;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ padding: 12px 14px;
+ border: 1px solid var(--line);
+ cursor: pointer;
+}
+
+.match-row:hover,
+button:hover,
+.link-button:hover {
+ background: var(--surface-2);
+}
+
+.match-main {
+ display: flex;
+ flex-direction: column;
+ align-items: start;
+ text-align: left;
+}
+
+.quality {
+ font-size: 12px;
+ color: var(--ink-soft);
+ text-transform: uppercase;
+}
+
+.settings {
+ max-width: 720px;
+ margin: 0 auto;
+ min-height: 100vh;
+}
+
+.settings-form {
+ display: grid;
+ gap: 16px;
+}
+
+label {
+ display: grid;
+ gap: 8px;
+}
+
+input,
+textarea {
+ width: 100%;
+ padding: 10px 12px;
+ border: 1px solid var(--line);
+ border-radius: 10px;
+ background: #fff;
+ color: var(--ink);
+ font: inherit;
+}
+
+button,
+.link-button {
+ padding: 10px 14px;
+ background: var(--accent);
+ color: #fff;
+ cursor: pointer;
+}
+
+.actions {
+ display: flex;
+ justify-content: end;
+}
diff --git a/cmd/keepassgo-browser-bridge/main.go b/cmd/keepassgo-browser-bridge/main.go
new file mode 100644
index 0000000..0fd8e8d
--- /dev/null
+++ b/cmd/keepassgo-browser-bridge/main.go
@@ -0,0 +1,121 @@
+package main
+
+import (
+ "context"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+
+ "git.julianfamily.org/keepassgo/internal/browserbridge"
+)
+
+func main() {
+ if len(os.Args) > 1 {
+ switch strings.TrimSpace(os.Args[1]) {
+ case "install-native-host":
+ if err := runInstallNativeHost(os.Args[2:]); err != nil {
+ fail(err)
+ }
+ return
+ case "status":
+ if err := runStatus(os.Args[2:]); err != nil {
+ fail(err)
+ }
+ return
+ }
+ }
+ if err := runNativeMessage(); err != nil {
+ _ = browserbridge.WriteResponse(os.Stdout, browserbridge.Response{Success: false, Error: err.Error()})
+ os.Exit(1)
+ }
+}
+
+func runInstallNativeHost(args []string) error {
+ fs := flag.NewFlagSet("install-native-host", flag.ContinueOnError)
+ browserName := fs.String("browser", string(browserbridge.BrowserFirefox), "target browser: firefox, chrome, chromium")
+ binaryPath := fs.String("binary", "", "path to keepassgo-browser-bridge binary")
+ extensionID := fs.String("extension-id", "", "browser extension id (required for chrome/chromium)")
+ outputPath := fs.String("output", "", "native host manifest output path")
+ if err := fs.Parse(args); err != nil {
+ return err
+ }
+ path := strings.TrimSpace(*binaryPath)
+ if path == "" {
+ resolved, err := defaultBinaryPath()
+ if err != nil {
+ return err
+ }
+ path = resolved
+ }
+ installed, err := browserbridge.InstallManifest(browserbridge.Browser(strings.TrimSpace(*browserName)), path, strings.TrimSpace(*extensionID), strings.TrimSpace(*outputPath))
+ if err != nil {
+ return err
+ }
+ fmt.Fprintln(os.Stdout, installed)
+ return nil
+}
+
+func runStatus(args []string) error {
+ fs := flag.NewFlagSet("status", flag.ContinueOnError)
+ grpcAddr := fs.String("grpc-addr", browserbridge.DefaultGRPCAddress, "KeePassGO local gRPC address")
+ token := fs.String("token", "", "KeePassGO API bearer token")
+ if err := fs.Parse(args); err != nil {
+ return err
+ }
+ req := browserbridge.Request{
+ Action: "status",
+ GRPCAddress: strings.TrimSpace(*grpcAddr),
+ BearerToken: strings.TrimSpace(*token),
+ }
+ connCfg, err := req.Connection()
+ if err != nil {
+ return err
+ }
+ conn, client, ctx, err := browserbridge.Dial(context.Background(), connCfg)
+ if err != nil {
+ return err
+ }
+ defer func() { _ = conn.Close() }()
+ resp := browserbridge.HandleRequest(ctx, req, client)
+ enc := json.NewEncoder(os.Stdout)
+ enc.SetIndent("", " ")
+ return enc.Encode(resp)
+}
+
+func runNativeMessage() error {
+ req, err := browserbridge.ReadRequest(os.Stdin)
+ if err != nil {
+ return err
+ }
+ connCfg, err := req.Connection()
+ if err != nil {
+ return browserbridge.WriteResponse(os.Stdout, browserbridge.Response{Success: false, Error: err.Error()})
+ }
+ conn, client, ctx, err := browserbridge.Dial(context.Background(), connCfg)
+ if err != nil {
+ return browserbridge.WriteResponse(os.Stdout, browserbridge.Response{Success: false, Error: err.Error()})
+ }
+ defer func() { _ = conn.Close() }()
+ return browserbridge.WriteResponse(os.Stdout, browserbridge.HandleRequest(ctx, req, client))
+}
+
+func defaultBinaryPath() (string, error) {
+ self, err := os.Executable()
+ if err == nil && strings.TrimSpace(self) != "" {
+ return self, nil
+ }
+ self, err = exec.LookPath("keepassgo-browser-bridge")
+ if err == nil {
+ return self, nil
+ }
+ return filepath.Abs("./keepassgo-browser-bridge")
+}
+
+func fail(err error) {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+}
diff --git a/docs/browser-extension.md b/docs/browser-extension.md
new file mode 100644
index 0000000..6fc9ae2
--- /dev/null
+++ b/docs/browser-extension.md
@@ -0,0 +1,76 @@
+# Browser Extension
+
+KeePassGO browser integration uses:
+
+- the existing local gRPC API in KeePassGO
+- API tokens for authorization
+- a tiny native messaging host for browser-to-gRPC transport adaptation
+
+The browser extension does **not** talk to vault files directly.
+
+## Security Model
+
+- KeePassGO remains the source of truth for authentication, authorization, approvals, and audit events.
+- The browser extension stores the gRPC address and API token in browser extension storage.
+- The native messaging host receives the token on each request from the extension.
+- The native messaging host uses the token only to attach `authorization: Bearer ...` metadata to the local gRPC request.
+- The native messaging host does not persist the token to disk.
+
+The native messaging host is therefore part of the trusted client for that browser profile. Scope the API token accordingly.
+
+## RPCs Used
+
+The browser integration uses:
+
+- `GetSessionStatus`
+- `FindBrowserLogins`
+- `GetBrowserCredential`
+
+The browser feature intentionally stays on the same secure gRPC surface used by other trusted automation.
+
+## Native Host
+
+Build the bridge:
+
+```bash
+go build ./cmd/keepassgo-browser-bridge
+```
+
+Install a Firefox native messaging manifest:
+
+```bash
+./keepassgo-browser-bridge install-native-host --browser firefox --binary /absolute/path/to/keepassgo-browser-bridge
+```
+
+Install a Chromium native messaging manifest:
+
+```bash
+./keepassgo-browser-bridge install-native-host --browser chromium --binary /absolute/path/to/keepassgo-browser-bridge --extension-id
+```
+
+Chrome and Chromium require the actual extension id in the native host manifest.
+
+## Extension Setup
+
+Firefox:
+
+1. Load `browser/extension/manifest.firefox.json` as a temporary add-on or package it as an extension.
+2. Open the extension settings page.
+3. Set the KeePassGO gRPC address, usually `127.0.0.1:47777`.
+4. Paste an API token scoped for browser login lookup and credential copy.
+
+Chromium / Chrome:
+
+1. Load `browser/extension/` with `manifest.chromium.json`.
+2. Note the extension id the browser assigns.
+3. Install the native host manifest with that extension id.
+4. Configure the gRPC address and API token in the extension settings page.
+
+## Required Token Scope
+
+At minimum, the browser token should have policy rules allowing:
+
+- `list_entries` for the groups you want the browser to search
+- `copy_username` for entries the browser may fill
+- `copy_password` for entries the browser may fill
+- `copy_url` for entries the browser may confirm against page URL
diff --git a/internal/api/server.go b/internal/api/server.go
index 8fdddfa..b52ea78 100644
--- a/internal/api/server.go
+++ b/internal/api/server.go
@@ -3,7 +3,9 @@ package api
import (
"context"
"errors"
+ "fmt"
"maps"
+ "net/url"
"os"
"slices"
"strings"
@@ -225,6 +227,133 @@ func (s *Server) UnlockVault(ctx context.Context, req *keepassgov1.UnlockVaultRe
return &keepassgov1.UnlockVaultResponse{}, nil
}
+func (s *Server) FindBrowserLogins(ctx context.Context, req *keepassgov1.FindBrowserLoginsRequest) (*keepassgov1.FindBrowserLoginsResponse, error) {
+ model, locked := s.snapshotModel()
+ if locked {
+ return nil, status.Error(codes.FailedPrecondition, "vault is locked")
+ }
+ token, err := s.authorizeVaultRequest(ctx, apitokens.OperationListEntries)
+ if err != nil {
+ return nil, err
+ }
+ pageHost, err := normalizedBrowserHost(req.GetPageUrl())
+ if err != nil {
+ return nil, status.Error(codes.InvalidArgument, err.Error())
+ }
+
+ type rankedMatch struct {
+ match *keepassgov1.BrowserLoginMatch
+ score int
+ }
+ var matches []rankedMatch
+ for _, entry := range visibleModel(model).Entries {
+ quality, score := classifyBrowserEntryMatch(pageHost, entry.URL)
+ if score == 0 {
+ continue
+ }
+ matches = append(matches, rankedMatch{
+ match: &keepassgov1.BrowserLoginMatch{
+ Id: entry.ID,
+ Title: entry.Title,
+ Username: entry.Username,
+ Url: entry.URL,
+ Path: append([]string(nil), entry.Path...),
+ Quality: quality,
+ },
+ score: score,
+ })
+ }
+ slices.SortFunc(matches, func(a, b rankedMatch) int {
+ switch {
+ case a.score != b.score:
+ return b.score - a.score
+ case a.match.GetTitle() != b.match.GetTitle():
+ return strings.Compare(a.match.GetTitle(), b.match.GetTitle())
+ case a.match.GetUsername() != b.match.GetUsername():
+ return strings.Compare(a.match.GetUsername(), b.match.GetUsername())
+ default:
+ return strings.Compare(a.match.GetId(), b.match.GetId())
+ }
+ })
+ out := make([]*keepassgov1.BrowserLoginMatch, 0, len(matches))
+ for _, match := range matches {
+ out = append(out, match.match)
+ }
+ switch len(out) {
+ case 1:
+ s.audit.Record(apiaudit.Event{
+ Type: apiaudit.EventAutofillFound,
+ TokenID: token.ID,
+ TokenName: token.Name,
+ ClientName: token.ClientName,
+ Operation: apitokens.OperationListEntries,
+ Message: "browser login match found for " + pageHost,
+ })
+ case 2, 3, 4, 5:
+ s.audit.Record(apiaudit.Event{
+ Type: apiaudit.EventAutofillAmbiguous,
+ TokenID: token.ID,
+ TokenName: token.Name,
+ ClientName: token.ClientName,
+ Operation: apitokens.OperationListEntries,
+ Message: "browser login search returned multiple matches for " + pageHost,
+ })
+ }
+ return &keepassgov1.FindBrowserLoginsResponse{Matches: out}, nil
+}
+
+func (s *Server) GetBrowserCredential(ctx context.Context, req *keepassgov1.GetBrowserCredentialRequest) (*keepassgov1.GetBrowserCredentialResponse, error) {
+ model, locked := s.snapshotModel()
+ if locked {
+ return nil, status.Error(codes.FailedPrecondition, "vault is locked")
+ }
+ token, err := s.authenticateRequest(ctx)
+ if err != nil {
+ return nil, err
+ }
+ entry, err := findEntryByID(model, req.GetId())
+ if err != nil {
+ return nil, status.Error(codes.NotFound, err.Error())
+ }
+ if pageURL := strings.TrimSpace(req.GetPageUrl()); pageURL != "" {
+ pageHost, err := normalizedBrowserHost(pageURL)
+ if err != nil {
+ return nil, status.Error(codes.InvalidArgument, err.Error())
+ }
+ if _, score := classifyBrowserEntryMatch(pageHost, entry.URL); score == 0 {
+ return nil, status.Error(codes.InvalidArgument, "entry url does not match requested page")
+ }
+ }
+ if strings.TrimSpace(entry.Username) != "" {
+ if _, err := s.authorizeResourceRequest(ctx, token, apitokens.OperationCopyUsername, apitokens.Resource{Kind: apitokens.ResourceEntry, EntryID: entry.ID, Path: entry.Path}); err != nil {
+ return nil, err
+ }
+ }
+ if _, err := s.authorizeResourceRequest(ctx, token, apitokens.OperationCopyPassword, apitokens.Resource{Kind: apitokens.ResourceEntry, EntryID: entry.ID, Path: entry.Path}); err != nil {
+ return nil, err
+ }
+ if strings.TrimSpace(entry.URL) != "" {
+ if _, err := s.authorizeResourceRequest(ctx, token, apitokens.OperationCopyURL, apitokens.Resource{Kind: apitokens.ResourceEntry, EntryID: entry.ID, Path: entry.Path}); err != nil {
+ return nil, err
+ }
+ }
+ s.audit.Record(apiaudit.Event{
+ Type: apiaudit.EventAutofillFound,
+ TokenID: token.ID,
+ TokenName: token.Name,
+ ClientName: token.ClientName,
+ Operation: apitokens.OperationCopyPassword,
+ Resource: apitokens.Resource{Kind: apitokens.ResourceEntry, EntryID: entry.ID, Path: entry.Path},
+ Message: "browser credential returned for " + entry.ID,
+ })
+ return &keepassgov1.GetBrowserCredentialResponse{
+ Id: entry.ID,
+ Username: entry.Username,
+ Password: entry.Password,
+ Url: entry.URL,
+ }, nil
+}
+
func mapLifecycleError(operation string, err error) error {
switch {
case errors.Is(err, os.ErrNotExist):
@@ -787,6 +916,39 @@ func findMutableEntryByID(model *vault.Model, id string) (vault.Entry, int, erro
return vault.Entry{}, -1, vault.ErrEntryNotFound
}
+func normalizedBrowserHost(raw string) (string, error) {
+ parsed, err := url.Parse(strings.TrimSpace(raw))
+ if err != nil {
+ return "", fmt.Errorf("parse page url: %w", err)
+ }
+ host := strings.ToLower(parsed.Hostname())
+ if host == "" {
+ return "", fmt.Errorf("page url must include a hostname")
+ }
+ return host, nil
+}
+
+func classifyBrowserEntryMatch(pageHost, rawEntryURL string) (string, int) {
+ parsed, err := url.Parse(strings.TrimSpace(rawEntryURL))
+ if err != nil {
+ return "", 0
+ }
+ entryHost := strings.ToLower(parsed.Hostname())
+ if entryHost == "" {
+ return "", 0
+ }
+ switch {
+ case pageHost == entryHost:
+ return "exact-host", 3
+ case strings.HasSuffix(pageHost, "."+entryHost):
+ return "subdomain", 2
+ case strings.HasSuffix(entryHost, "."+pageHost):
+ return "parent-domain", 1
+ default:
+ return "", 0
+ }
+}
+
func visibleModel(model vault.Model) vault.Model {
out := model
out.Entries = nil
diff --git a/internal/api/server_test.go b/internal/api/server_test.go
index 80c6112..d02be90 100644
--- a/internal/api/server_test.go
+++ b/internal/api/server_test.go
@@ -159,6 +159,84 @@ func TestVaultServiceRejectsUnauthorizedPasswordGeneration(t *testing.T) {
}
}
+func TestVaultServiceFindsBrowserLoginsForAuthorizedClients(t *testing.T) {
+ t.Parallel()
+
+ client, _, cleanup := newTestClient(t)
+ defer cleanup()
+
+ ctx := tokenContext(defaultTestTokenSecret)
+ resp, err := client.FindBrowserLogins(ctx, &keepassgov1.FindBrowserLoginsRequest{
+ PageUrl: "https://vault.crew.example.invalid/login",
+ })
+ if err != nil {
+ t.Fatalf("FindBrowserLogins() error = %v", err)
+ }
+ if len(resp.Matches) != 1 {
+ t.Fatalf("len(FindBrowserLogins().Matches) = %d, want 1", len(resp.Matches))
+ }
+ if resp.Matches[0].Id != "vault-console" {
+ t.Fatalf("FindBrowserLogins().Matches[0].Id = %q, want vault-console", resp.Matches[0].Id)
+ }
+ if resp.Matches[0].Quality != "exact-host" {
+ t.Fatalf("FindBrowserLogins().Matches[0].Quality = %q, want exact-host", resp.Matches[0].Quality)
+ }
+}
+
+func TestVaultServiceGetsBrowserCredentialForAuthorizedClients(t *testing.T) {
+ t.Parallel()
+
+ client, _, cleanup := newTestClient(t)
+ defer cleanup()
+
+ ctx := tokenContext(defaultTestTokenSecret)
+ resp, err := client.GetBrowserCredential(ctx, &keepassgov1.GetBrowserCredentialRequest{
+ Id: "vault-console",
+ PageUrl: "https://vault.crew.example.invalid/login",
+ })
+ if err != nil {
+ t.Fatalf("GetBrowserCredential() error = %v", err)
+ }
+ if resp.Id != "vault-console" {
+ t.Fatalf("GetBrowserCredential().Id = %q, want vault-console", resp.Id)
+ }
+ if resp.Password != "token-1" {
+ t.Fatalf("GetBrowserCredential().Password = %q, want token-1", resp.Password)
+ }
+}
+
+func TestVaultServiceRejectsUnauthorizedBrowserCredentialAccess(t *testing.T) {
+ t.Parallel()
+
+ client, _, cleanup := newTestClientForModel(t, vault.Model{
+ Entries: []vault.Entry{
+ {
+ ID: "vault-console",
+ Title: "Vault Console",
+ Username: "dannyocean",
+ Password: "token-1",
+ URL: "https://vault.crew.example.invalid",
+ Path: []string{"Root", "Internet"},
+ },
+ testAPITokenEntry(t,
+ apitokens.PolicyRule{Effect: apitokens.EffectAllow, Operation: apitokens.OperationListEntries, Resource: apitokens.Resource{Kind: apitokens.ResourceGroup, Path: []string{"Root"}}},
+ apitokens.PolicyRule{Effect: apitokens.EffectAllow, Operation: apitokens.OperationCopyUsername, Resource: apitokens.Resource{Kind: apitokens.ResourceEntry, EntryID: "vault-console", Path: []string{"Root", "Internet"}}},
+ apitokens.PolicyRule{Effect: apitokens.EffectAllow, Operation: apitokens.OperationCopyURL, Resource: apitokens.Resource{Kind: apitokens.ResourceEntry, EntryID: "vault-console", Path: []string{"Root", "Internet"}}},
+ apitokens.PolicyRule{Effect: apitokens.EffectDeny, Operation: apitokens.OperationCopyPassword, Resource: apitokens.Resource{Kind: apitokens.ResourceEntry, EntryID: "vault-console", Path: []string{"Root", "Internet"}}},
+ ),
+ },
+ })
+ defer cleanup()
+
+ _, err := client.GetBrowserCredential(tokenContext(defaultTestTokenSecret), &keepassgov1.GetBrowserCredentialRequest{
+ Id: "vault-console",
+ PageUrl: "https://vault.crew.example.invalid/login",
+ })
+ if status.Code(err) != codes.PermissionDenied {
+ t.Fatalf("GetBrowserCredential() code = %v, want %v", status.Code(err), codes.PermissionDenied)
+ }
+}
+
func TestVaultServicePromptsAndResumesWhenApproved(t *testing.T) {
t.Parallel()
diff --git a/internal/browserbridge/bridge.go b/internal/browserbridge/bridge.go
new file mode 100644
index 0000000..1e9f05f
--- /dev/null
+++ b/internal/browserbridge/bridge.go
@@ -0,0 +1,321 @@
+package browserbridge
+
+import (
+ "context"
+ "encoding/binary"
+ "encoding/json"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "strings"
+
+ keepassgov1 "git.julianfamily.org/keepassgo/proto/keepassgo/v1"
+)
+
+const (
+ NativeHostName = "org.keepassgo.browser"
+ DefaultGRPCAddress = "127.0.0.1:47777"
+ defaultFirefoxID = "browser@keepassgo.invalid"
+ maxNativeMessageSize = 1024 * 1024
+)
+
+type Request struct {
+ Action string `json:"action"`
+ GRPCAddress string `json:"grpcAddress,omitempty"`
+ BearerToken string `json:"bearerToken,omitempty"`
+ URL string `json:"url,omitempty"`
+ EntryID string `json:"entryId,omitempty"`
+}
+
+type Response struct {
+ Success bool `json:"success"`
+ Error string `json:"error,omitempty"`
+ Status *Status `json:"status,omitempty"`
+ Matches []Match `json:"matches,omitempty"`
+ Credential *Credential `json:"credential,omitempty"`
+ Version string `json:"version,omitempty"`
+}
+
+type Status struct {
+ Connected bool `json:"connected"`
+ Locked bool `json:"locked"`
+ Dirty bool `json:"dirty,omitempty"`
+ EntryCount uint32 `json:"entryCount,omitempty"`
+ GRPCAddress string `json:"grpcAddress,omitempty"`
+}
+
+type Match struct {
+ ID string `json:"id"`
+ Title string `json:"title"`
+ Username string `json:"username,omitempty"`
+ URL string `json:"url,omitempty"`
+ Path []string `json:"path,omitempty"`
+ Quality string `json:"quality,omitempty"`
+}
+
+type Credential struct {
+ ID string `json:"id"`
+ Username string `json:"username,omitempty"`
+ Password string `json:"password,omitempty"`
+ URL string `json:"url,omitempty"`
+}
+
+type Connection struct {
+ GRPCAddress string
+ BearerToken string
+}
+
+type Client interface {
+ Status(context.Context) (*keepassgov1.GetSessionStatusResponse, error)
+ FindBrowserLogins(context.Context, string) ([]*keepassgov1.BrowserLoginMatch, error)
+ GetBrowserCredential(context.Context, string, string) (*keepassgov1.GetBrowserCredentialResponse, error)
+}
+
+type Browser string
+
+const (
+ BrowserFirefox Browser = "firefox"
+ BrowserChrome Browser = "chrome"
+ BrowserChromium Browser = "chromium"
+)
+
+type NativeHostManifest struct {
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Path string `json:"path"`
+ Type string `json:"type"`
+ AllowedExtensions []string `json:"allowed_extensions,omitempty"`
+ AllowedOrigins []string `json:"allowed_origins,omitempty"`
+}
+
+func DefaultFirefoxExtensionID() string {
+ return defaultFirefoxID
+}
+
+func ReadRequest(r io.Reader) (Request, error) {
+ var sizeBuf [4]byte
+ if _, err := io.ReadFull(r, sizeBuf[:]); err != nil {
+ return Request{}, err
+ }
+ size := binary.LittleEndian.Uint32(sizeBuf[:])
+ if size == 0 || size > maxNativeMessageSize {
+ return Request{}, fmt.Errorf("invalid native message size %d", size)
+ }
+ body := make([]byte, size)
+ if _, err := io.ReadFull(r, body); err != nil {
+ return Request{}, err
+ }
+ var req Request
+ if err := json.Unmarshal(body, &req); err != nil {
+ return Request{}, fmt.Errorf("decode native request: %w", err)
+ }
+ return req, nil
+}
+
+func WriteResponse(w io.Writer, resp Response) error {
+ data, err := json.Marshal(resp)
+ if err != nil {
+ return fmt.Errorf("encode native response: %w", err)
+ }
+ if len(data) > maxNativeMessageSize {
+ return fmt.Errorf("native response too large: %d", len(data))
+ }
+ var sizeBuf [4]byte
+ binary.LittleEndian.PutUint32(sizeBuf[:], uint32(len(data)))
+ if _, err := w.Write(sizeBuf[:]); err != nil {
+ return err
+ }
+ _, err = w.Write(data)
+ return err
+}
+
+func (r Request) Connection() (Connection, error) {
+ conn := Connection{
+ GRPCAddress: strings.TrimSpace(r.GRPCAddress),
+ BearerToken: strings.TrimSpace(r.BearerToken),
+ }
+ if conn.GRPCAddress == "" {
+ conn.GRPCAddress = DefaultGRPCAddress
+ }
+ if conn.BearerToken == "" {
+ return Connection{}, fmt.Errorf("browser bridge bearer token is required")
+ }
+ return conn, nil
+}
+
+func HandleRequest(ctx context.Context, req Request, client Client) Response {
+ conn, err := req.Connection()
+ if err != nil {
+ return Response{Success: false, Error: err.Error()}
+ }
+ action := strings.TrimSpace(req.Action)
+ switch action {
+ case "status":
+ status, err := statusResponse(ctx, client, conn.GRPCAddress)
+ if err != nil {
+ return Response{Success: false, Error: err.Error(), Status: disconnectedStatus(conn.GRPCAddress)}
+ }
+ return Response{Success: true, Status: status, Version: "1"}
+ case "find-logins":
+ status, err := statusResponse(ctx, client, conn.GRPCAddress)
+ if err != nil {
+ return Response{Success: false, Error: err.Error(), Status: disconnectedStatus(conn.GRPCAddress)}
+ }
+ if status.Locked {
+ return Response{Success: true, Status: status, Matches: nil, Version: "1"}
+ }
+ matches, err := findMatches(ctx, client, req.URL)
+ if err != nil {
+ return Response{Success: false, Error: err.Error(), Status: status}
+ }
+ return Response{Success: true, Status: status, Matches: matches, Version: "1"}
+ case "get-login":
+ status, err := statusResponse(ctx, client, conn.GRPCAddress)
+ if err != nil {
+ return Response{Success: false, Error: err.Error(), Status: disconnectedStatus(conn.GRPCAddress)}
+ }
+ if status.Locked {
+ return Response{Success: false, Error: "vault is locked", Status: status}
+ }
+ credential, err := loadCredential(ctx, client, req.EntryID, req.URL)
+ if err != nil {
+ return Response{Success: false, Error: err.Error(), Status: status}
+ }
+ return Response{Success: true, Status: status, Credential: credential, Version: "1"}
+ default:
+ return Response{Success: false, Error: fmt.Sprintf("unsupported action %q", action)}
+ }
+}
+
+func disconnectedStatus(addr string) *Status {
+ return &Status{Connected: false, GRPCAddress: strings.TrimSpace(addr)}
+}
+
+func statusResponse(ctx context.Context, client Client, addr string) (*Status, error) {
+ resp, err := client.Status(ctx)
+ if err != nil {
+ return nil, err
+ }
+ return &Status{
+ Connected: true,
+ Locked: resp.GetLocked(),
+ Dirty: resp.GetDirty(),
+ EntryCount: resp.GetEntryCount(),
+ GRPCAddress: strings.TrimSpace(addr),
+ }, nil
+}
+
+func findMatches(ctx context.Context, client Client, rawURL string) ([]Match, error) {
+ resp, err := client.FindBrowserLogins(ctx, strings.TrimSpace(rawURL))
+ if err != nil {
+ return nil, err
+ }
+ out := make([]Match, 0, len(resp))
+ for _, match := range resp {
+ out = append(out, Match{
+ ID: match.GetId(),
+ Title: match.GetTitle(),
+ Username: match.GetUsername(),
+ URL: match.GetUrl(),
+ Path: append([]string(nil), match.GetPath()...),
+ Quality: match.GetQuality(),
+ })
+ }
+ return out, nil
+}
+
+func loadCredential(ctx context.Context, client Client, entryID, rawURL string) (*Credential, error) {
+ id := strings.TrimSpace(entryID)
+ if id == "" {
+ return nil, fmt.Errorf("entry id is required")
+ }
+ resp, err := client.GetBrowserCredential(ctx, id, strings.TrimSpace(rawURL))
+ if err != nil {
+ return nil, err
+ }
+ return &Credential{
+ ID: resp.GetId(),
+ Username: resp.GetUsername(),
+ Password: resp.GetPassword(),
+ URL: resp.GetUrl(),
+ }, nil
+}
+
+func Manifest(browser Browser, binaryPath, extensionID string) (NativeHostManifest, error) {
+ path := strings.TrimSpace(binaryPath)
+ if path == "" {
+ return NativeHostManifest{}, fmt.Errorf("native host binary path is required")
+ }
+ switch browser {
+ case BrowserFirefox:
+ id := strings.TrimSpace(extensionID)
+ if id == "" {
+ id = defaultFirefoxID
+ }
+ return NativeHostManifest{
+ Name: NativeHostName,
+ Description: "KeePassGO browser bridge",
+ Path: path,
+ Type: "stdio",
+ AllowedExtensions: []string{id},
+ }, nil
+ case BrowserChrome, BrowserChromium:
+ id := strings.TrimSpace(extensionID)
+ if id == "" {
+ return NativeHostManifest{}, fmt.Errorf("%s extension id is required", browser)
+ }
+ return NativeHostManifest{
+ Name: NativeHostName,
+ Description: "KeePassGO browser bridge",
+ Path: path,
+ Type: "stdio",
+ AllowedOrigins: []string{"chrome-extension://" + id + "/"},
+ }, nil
+ default:
+ return NativeHostManifest{}, fmt.Errorf("unsupported browser %q", browser)
+ }
+}
+
+func DefaultManifestPath(browser Browser) (string, error) {
+ home, err := os.UserHomeDir()
+ if err != nil {
+ return "", err
+ }
+ switch browser {
+ case BrowserFirefox:
+ return filepath.Join(home, ".mozilla", "native-messaging-hosts", NativeHostName+".json"), nil
+ case BrowserChrome:
+ return filepath.Join(home, ".config", "google-chrome", "NativeMessagingHosts", NativeHostName+".json"), nil
+ case BrowserChromium:
+ return filepath.Join(home, ".config", "chromium", "NativeMessagingHosts", NativeHostName+".json"), nil
+ default:
+ return "", fmt.Errorf("unsupported browser %q", browser)
+ }
+}
+
+func InstallManifest(browser Browser, binaryPath, extensionID, outputPath string) (string, error) {
+ manifest, err := Manifest(browser, binaryPath, extensionID)
+ if err != nil {
+ return "", err
+ }
+ path := strings.TrimSpace(outputPath)
+ if path == "" {
+ path, err = DefaultManifestPath(browser)
+ if err != nil {
+ return "", err
+ }
+ }
+ if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
+ return "", fmt.Errorf("create native host manifest dir: %w", err)
+ }
+ data, err := json.MarshalIndent(manifest, "", " ")
+ if err != nil {
+ return "", fmt.Errorf("encode native host manifest: %w", err)
+ }
+ data = append(data, '\n')
+ if err := os.WriteFile(path, data, 0o644); err != nil {
+ return "", fmt.Errorf("write native host manifest: %w", err)
+ }
+ return path, nil
+}
diff --git a/internal/browserbridge/bridge_test.go b/internal/browserbridge/bridge_test.go
new file mode 100644
index 0000000..f9b360c
--- /dev/null
+++ b/internal/browserbridge/bridge_test.go
@@ -0,0 +1,182 @@
+package browserbridge
+
+import (
+ "bytes"
+ "context"
+ "encoding/binary"
+ "encoding/json"
+ "os"
+ "path/filepath"
+ "testing"
+
+ keepassgov1 "git.julianfamily.org/keepassgo/proto/keepassgo/v1"
+)
+
+func TestReadRequestAndWriteResponse(t *testing.T) {
+ t.Parallel()
+
+ var input bytes.Buffer
+ body, err := json.Marshal(Request{
+ Action: "find-logins",
+ GRPCAddress: "127.0.0.1:47777",
+ BearerToken: "secret",
+ URL: "https://example.invalid/login",
+ })
+ if err != nil {
+ t.Fatalf("Marshal() error = %v", err)
+ }
+ if err := binary.Write(&input, binary.LittleEndian, uint32(len(body))); err != nil {
+ t.Fatalf("binary.Write() error = %v", err)
+ }
+ if _, err := input.Write(body); err != nil {
+ t.Fatalf("Write() error = %v", err)
+ }
+
+ req, err := ReadRequest(&input)
+ if err != nil {
+ t.Fatalf("ReadRequest() error = %v", err)
+ }
+ if req.Action != "find-logins" || req.BearerToken != "secret" {
+ t.Fatalf("ReadRequest() = %#v, want action and token preserved", req)
+ }
+
+ var output bytes.Buffer
+ if err := WriteResponse(&output, Response{Success: true, Version: "1"}); err != nil {
+ t.Fatalf("WriteResponse() error = %v", err)
+ }
+ var size uint32
+ if err := binary.Read(&output, binary.LittleEndian, &size); err != nil {
+ t.Fatalf("binary.Read() error = %v", err)
+ }
+ payload := make([]byte, size)
+ if _, err := output.Read(payload); err != nil {
+ t.Fatalf("Read() payload error = %v", err)
+ }
+ var resp Response
+ if err := json.Unmarshal(payload, &resp); err != nil {
+ t.Fatalf("Unmarshal() error = %v", err)
+ }
+ if !resp.Success || resp.Version != "1" {
+ t.Fatalf("response = %#v, want success version 1", resp)
+ }
+}
+
+func TestHandleRequestFindLogins(t *testing.T) {
+ t.Parallel()
+
+ client := fakeClient{
+ status: &keepassgov1.GetSessionStatusResponse{Locked: false, EntryCount: 2},
+ matches: []*keepassgov1.BrowserLoginMatch{
+ {Id: "vault-console", Title: "Vault Console", Username: "dannyocean", Url: "https://vault.example.invalid", Quality: "exact-host"},
+ },
+ }
+ resp := HandleRequest(context.Background(), Request{
+ Action: "find-logins",
+ BearerToken: "secret",
+ URL: "https://vault.example.invalid/login",
+ }, client)
+ if !resp.Success {
+ t.Fatalf("HandleRequest() success = false, error = %q", resp.Error)
+ }
+ if len(resp.Matches) != 1 || resp.Matches[0].ID != "vault-console" {
+ t.Fatalf("HandleRequest().Matches = %#v, want vault-console", resp.Matches)
+ }
+}
+
+func TestHandleRequestGetLogin(t *testing.T) {
+ t.Parallel()
+
+ client := fakeClient{
+ status: &keepassgov1.GetSessionStatusResponse{Locked: false, EntryCount: 1},
+ credential: &keepassgov1.GetBrowserCredentialResponse{
+ Id: "vault-console",
+ Username: "dannyocean",
+ Password: "token-1",
+ Url: "https://vault.example.invalid",
+ },
+ }
+ resp := HandleRequest(context.Background(), Request{
+ Action: "get-login",
+ BearerToken: "secret",
+ EntryID: "vault-console",
+ URL: "https://vault.example.invalid/login",
+ }, client)
+ if !resp.Success {
+ t.Fatalf("HandleRequest() success = false, error = %q", resp.Error)
+ }
+ if resp.Credential == nil || resp.Credential.ID != "vault-console" {
+ t.Fatalf("HandleRequest().Credential = %#v, want vault-console", resp.Credential)
+ }
+}
+
+func TestHandleRequestRequiresBearerToken(t *testing.T) {
+ t.Parallel()
+
+ resp := HandleRequest(context.Background(), Request{Action: "status"}, fakeClient{})
+ if resp.Success {
+ t.Fatal("HandleRequest().Success = true, want false without token")
+ }
+}
+
+func TestInstallManifest(t *testing.T) {
+ t.Parallel()
+
+ tmp := t.TempDir()
+ binaryPath := filepath.Join(tmp, "keepassgo-browser-bridge")
+ if err := os.WriteFile(binaryPath, []byte("#!/bin/sh\n"), 0o755); err != nil {
+ t.Fatalf("WriteFile(binary) error = %v", err)
+ }
+
+ path, err := InstallManifest(BrowserFirefox, binaryPath, "", filepath.Join(tmp, "firefox-host.json"))
+ if err != nil {
+ t.Fatalf("InstallManifest() error = %v", err)
+ }
+ data, err := os.ReadFile(path)
+ if err != nil {
+ t.Fatalf("ReadFile() error = %v", err)
+ }
+ var manifest NativeHostManifest
+ if err := json.Unmarshal(data, &manifest); err != nil {
+ t.Fatalf("Unmarshal() error = %v", err)
+ }
+ if manifest.Path != binaryPath {
+ t.Fatalf("manifest.Path = %q, want %q", manifest.Path, binaryPath)
+ }
+ if len(manifest.AllowedExtensions) != 1 || manifest.AllowedExtensions[0] != DefaultFirefoxExtensionID() {
+ t.Fatalf("manifest.AllowedExtensions = %#v, want default firefox extension id", manifest.AllowedExtensions)
+ }
+}
+
+type fakeClient struct {
+ status *keepassgov1.GetSessionStatusResponse
+ matches []*keepassgov1.BrowserLoginMatch
+ credential *keepassgov1.GetBrowserCredentialResponse
+ err error
+}
+
+func (f fakeClient) Status(context.Context) (*keepassgov1.GetSessionStatusResponse, error) {
+ if f.err != nil {
+ return nil, f.err
+ }
+ if f.status == nil {
+ return &keepassgov1.GetSessionStatusResponse{}, nil
+ }
+ return f.status, nil
+}
+
+func (f fakeClient) FindBrowserLogins(context.Context, string) ([]*keepassgov1.BrowserLoginMatch, error) {
+ if f.err != nil {
+ return nil, f.err
+ }
+ return f.matches, nil
+}
+
+func (f fakeClient) GetBrowserCredential(context.Context, string, string) (*keepassgov1.GetBrowserCredentialResponse, error) {
+ if f.err != nil {
+ return nil, f.err
+ }
+ if f.credential == nil {
+ return &keepassgov1.GetBrowserCredentialResponse{}, nil
+ }
+ return f.credential, nil
+}
diff --git a/internal/browserbridge/client.go b/internal/browserbridge/client.go
new file mode 100644
index 0000000..6a5f37f
--- /dev/null
+++ b/internal/browserbridge/client.go
@@ -0,0 +1,59 @@
+package browserbridge
+
+import (
+ "context"
+ "fmt"
+ "net"
+ "strings"
+
+ keepassgov1 "git.julianfamily.org/keepassgo/proto/keepassgo/v1"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/credentials/insecure"
+ "google.golang.org/grpc/metadata"
+)
+
+type GRPCClient struct {
+ client keepassgov1.VaultServiceClient
+}
+
+func Dial(ctx context.Context, conn Connection) (*grpc.ClientConn, *GRPCClient, context.Context, error) {
+ if strings.TrimSpace(conn.GRPCAddress) == "" {
+ conn.GRPCAddress = DefaultGRPCAddress
+ }
+ if strings.TrimSpace(conn.BearerToken) == "" {
+ return nil, nil, nil, fmt.Errorf("browser bridge bearer token is required")
+ }
+ address := strings.TrimSpace(conn.GRPCAddress)
+ grpcConn, err := grpc.NewClient("passthrough:///"+address,
+ grpc.WithTransportCredentials(insecure.NewCredentials()),
+ grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) {
+ return net.Dial("tcp", address)
+ }),
+ )
+ if err != nil {
+ return nil, nil, nil, fmt.Errorf("dial gRPC host %s: %w", address, err)
+ }
+ ctx = metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+strings.TrimSpace(conn.BearerToken))
+ return grpcConn, &GRPCClient{client: keepassgov1.NewVaultServiceClient(grpcConn)}, ctx, nil
+}
+
+func (c *GRPCClient) Status(ctx context.Context) (*keepassgov1.GetSessionStatusResponse, error) {
+ return c.client.GetSessionStatus(ctx, &keepassgov1.GetSessionStatusRequest{})
+}
+
+func (c *GRPCClient) FindBrowserLogins(ctx context.Context, pageURL string) ([]*keepassgov1.BrowserLoginMatch, error) {
+ resp, err := c.client.FindBrowserLogins(ctx, &keepassgov1.FindBrowserLoginsRequest{
+ PageUrl: strings.TrimSpace(pageURL),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return resp.GetMatches(), nil
+}
+
+func (c *GRPCClient) GetBrowserCredential(ctx context.Context, entryID, pageURL string) (*keepassgov1.GetBrowserCredentialResponse, error) {
+ return c.client.GetBrowserCredential(ctx, &keepassgov1.GetBrowserCredentialRequest{
+ Id: strings.TrimSpace(entryID),
+ PageUrl: strings.TrimSpace(pageURL),
+ })
+}
diff --git a/packaging/archlinux/keepassgo-git/PKGBUILD.tmpl b/packaging/archlinux/keepassgo-git/PKGBUILD.tmpl
index fc6e40b..9bd7a05 100644
--- a/packaging/archlinux/keepassgo-git/PKGBUILD.tmpl
+++ b/packaging/archlinux/keepassgo-git/PKGBUILD.tmpl
@@ -42,12 +42,14 @@ build() {
local app_version
app_version="$(git describe --tags --always --dirty)"
go build -ldflags "-X git.julianfamily.org/keepassgo/internal/appui.appVersion=${app_version}" -o keepassgo ./cmd/keepassgo
+ go build -ldflags "-X git.julianfamily.org/keepassgo/internal/appui.appVersion=${app_version}" -o keepassgo-browser-bridge ./cmd/keepassgo-browser-bridge
}
package() {
cd "$(_repo_dir)"
install -Dm755 keepassgo "${pkgdir}/usr/bin/keepassgo"
+ install -Dm755 keepassgo-browser-bridge "${pkgdir}/usr/bin/keepassgo-browser-bridge"
install -Dm644 internal/assets/keepassgo-icon.png \
"${pkgdir}/usr/share/icons/hicolor/512x512/apps/keepassgo.png"
install -Dm644 internal/assets/keepassgo-icon.svg \
diff --git a/proto/keepassgo/v1/keepassgo.pb.go b/proto/keepassgo/v1/keepassgo.pb.go
index 92e07f2..c798612 100644
--- a/proto/keepassgo/v1/keepassgo.pb.go
+++ b/proto/keepassgo/v1/keepassgo.pb.go
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
-// protoc v6.33.1
+// protoc v7.34.1
// source: proto/keepassgo/v1/keepassgo.proto
package keepassgov1
@@ -565,6 +565,298 @@ func (*UnlockVaultResponse) Descriptor() ([]byte, []int) {
return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{11}
}
+type FindBrowserLoginsRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ PageUrl string `protobuf:"bytes,1,opt,name=page_url,json=pageUrl,proto3" json:"page_url,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *FindBrowserLoginsRequest) Reset() {
+ *x = FindBrowserLoginsRequest{}
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *FindBrowserLoginsRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FindBrowserLoginsRequest) ProtoMessage() {}
+
+func (x *FindBrowserLoginsRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[12]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FindBrowserLoginsRequest.ProtoReflect.Descriptor instead.
+func (*FindBrowserLoginsRequest) Descriptor() ([]byte, []int) {
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *FindBrowserLoginsRequest) GetPageUrl() string {
+ if x != nil {
+ return x.PageUrl
+ }
+ return ""
+}
+
+type BrowserLoginMatch struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"`
+ Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"`
+ Url string `protobuf:"bytes,4,opt,name=url,proto3" json:"url,omitempty"`
+ Path []string `protobuf:"bytes,5,rep,name=path,proto3" json:"path,omitempty"`
+ Quality string `protobuf:"bytes,6,opt,name=quality,proto3" json:"quality,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *BrowserLoginMatch) Reset() {
+ *x = BrowserLoginMatch{}
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[13]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *BrowserLoginMatch) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BrowserLoginMatch) ProtoMessage() {}
+
+func (x *BrowserLoginMatch) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[13]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use BrowserLoginMatch.ProtoReflect.Descriptor instead.
+func (*BrowserLoginMatch) Descriptor() ([]byte, []int) {
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{13}
+}
+
+func (x *BrowserLoginMatch) GetId() string {
+ if x != nil {
+ return x.Id
+ }
+ return ""
+}
+
+func (x *BrowserLoginMatch) GetTitle() string {
+ if x != nil {
+ return x.Title
+ }
+ return ""
+}
+
+func (x *BrowserLoginMatch) GetUsername() string {
+ if x != nil {
+ return x.Username
+ }
+ return ""
+}
+
+func (x *BrowserLoginMatch) GetUrl() string {
+ if x != nil {
+ return x.Url
+ }
+ return ""
+}
+
+func (x *BrowserLoginMatch) GetPath() []string {
+ if x != nil {
+ return x.Path
+ }
+ return nil
+}
+
+func (x *BrowserLoginMatch) GetQuality() string {
+ if x != nil {
+ return x.Quality
+ }
+ return ""
+}
+
+type FindBrowserLoginsResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Matches []*BrowserLoginMatch `protobuf:"bytes,1,rep,name=matches,proto3" json:"matches,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *FindBrowserLoginsResponse) Reset() {
+ *x = FindBrowserLoginsResponse{}
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[14]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *FindBrowserLoginsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FindBrowserLoginsResponse) ProtoMessage() {}
+
+func (x *FindBrowserLoginsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[14]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FindBrowserLoginsResponse.ProtoReflect.Descriptor instead.
+func (*FindBrowserLoginsResponse) Descriptor() ([]byte, []int) {
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{14}
+}
+
+func (x *FindBrowserLoginsResponse) GetMatches() []*BrowserLoginMatch {
+ if x != nil {
+ return x.Matches
+ }
+ return nil
+}
+
+type GetBrowserCredentialRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ PageUrl string `protobuf:"bytes,2,opt,name=page_url,json=pageUrl,proto3" json:"page_url,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *GetBrowserCredentialRequest) Reset() {
+ *x = GetBrowserCredentialRequest{}
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[15]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *GetBrowserCredentialRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetBrowserCredentialRequest) ProtoMessage() {}
+
+func (x *GetBrowserCredentialRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[15]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetBrowserCredentialRequest.ProtoReflect.Descriptor instead.
+func (*GetBrowserCredentialRequest) Descriptor() ([]byte, []int) {
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{15}
+}
+
+func (x *GetBrowserCredentialRequest) GetId() string {
+ if x != nil {
+ return x.Id
+ }
+ return ""
+}
+
+func (x *GetBrowserCredentialRequest) GetPageUrl() string {
+ if x != nil {
+ return x.PageUrl
+ }
+ return ""
+}
+
+type GetBrowserCredentialResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
+ Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
+ Url string `protobuf:"bytes,4,opt,name=url,proto3" json:"url,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *GetBrowserCredentialResponse) Reset() {
+ *x = GetBrowserCredentialResponse{}
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[16]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *GetBrowserCredentialResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetBrowserCredentialResponse) ProtoMessage() {}
+
+func (x *GetBrowserCredentialResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[16]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetBrowserCredentialResponse.ProtoReflect.Descriptor instead.
+func (*GetBrowserCredentialResponse) Descriptor() ([]byte, []int) {
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{16}
+}
+
+func (x *GetBrowserCredentialResponse) GetId() string {
+ if x != nil {
+ return x.Id
+ }
+ return ""
+}
+
+func (x *GetBrowserCredentialResponse) GetUsername() string {
+ if x != nil {
+ return x.Username
+ }
+ return ""
+}
+
+func (x *GetBrowserCredentialResponse) GetPassword() string {
+ if x != nil {
+ return x.Password
+ }
+ return ""
+}
+
+func (x *GetBrowserCredentialResponse) GetUrl() string {
+ if x != nil {
+ return x.Url
+ }
+ return ""
+}
+
type ListEntriesRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Path []string `protobuf:"bytes,1,rep,name=path,proto3" json:"path,omitempty"`
@@ -575,7 +867,7 @@ type ListEntriesRequest struct {
func (x *ListEntriesRequest) Reset() {
*x = ListEntriesRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[12]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -587,7 +879,7 @@ func (x *ListEntriesRequest) String() string {
func (*ListEntriesRequest) ProtoMessage() {}
func (x *ListEntriesRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[12]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[17]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -600,7 +892,7 @@ func (x *ListEntriesRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListEntriesRequest.ProtoReflect.Descriptor instead.
func (*ListEntriesRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{12}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{17}
}
func (x *ListEntriesRequest) GetPath() []string {
@@ -634,7 +926,7 @@ type Entry struct {
func (x *Entry) Reset() {
*x = Entry{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[13]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -646,7 +938,7 @@ func (x *Entry) String() string {
func (*Entry) ProtoMessage() {}
func (x *Entry) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[13]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[18]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -659,7 +951,7 @@ func (x *Entry) ProtoReflect() protoreflect.Message {
// Deprecated: Use Entry.ProtoReflect.Descriptor instead.
func (*Entry) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{13}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{18}
}
func (x *Entry) GetId() string {
@@ -734,7 +1026,7 @@ type ListEntriesResponse struct {
func (x *ListEntriesResponse) Reset() {
*x = ListEntriesResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[14]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -746,7 +1038,7 @@ func (x *ListEntriesResponse) String() string {
func (*ListEntriesResponse) ProtoMessage() {}
func (x *ListEntriesResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[14]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[19]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -759,7 +1051,7 @@ func (x *ListEntriesResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListEntriesResponse.ProtoReflect.Descriptor instead.
func (*ListEntriesResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{14}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{19}
}
func (x *ListEntriesResponse) GetEntries() []*Entry {
@@ -778,7 +1070,7 @@ type ListGroupsRequest struct {
func (x *ListGroupsRequest) Reset() {
*x = ListGroupsRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[15]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -790,7 +1082,7 @@ func (x *ListGroupsRequest) String() string {
func (*ListGroupsRequest) ProtoMessage() {}
func (x *ListGroupsRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[15]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[20]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -803,7 +1095,7 @@ func (x *ListGroupsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListGroupsRequest.ProtoReflect.Descriptor instead.
func (*ListGroupsRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{15}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{20}
}
func (x *ListGroupsRequest) GetPath() []string {
@@ -822,7 +1114,7 @@ type ListGroupsResponse struct {
func (x *ListGroupsResponse) Reset() {
*x = ListGroupsResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[16]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -834,7 +1126,7 @@ func (x *ListGroupsResponse) String() string {
func (*ListGroupsResponse) ProtoMessage() {}
func (x *ListGroupsResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[16]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[21]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -847,7 +1139,7 @@ func (x *ListGroupsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListGroupsResponse.ProtoReflect.Descriptor instead.
func (*ListGroupsResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{16}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{21}
}
func (x *ListGroupsResponse) GetNames() []string {
@@ -867,7 +1159,7 @@ type CreateGroupRequest struct {
func (x *CreateGroupRequest) Reset() {
*x = CreateGroupRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[17]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -879,7 +1171,7 @@ func (x *CreateGroupRequest) String() string {
func (*CreateGroupRequest) ProtoMessage() {}
func (x *CreateGroupRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[17]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[22]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -892,7 +1184,7 @@ func (x *CreateGroupRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use CreateGroupRequest.ProtoReflect.Descriptor instead.
func (*CreateGroupRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{17}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{22}
}
func (x *CreateGroupRequest) GetParentPath() []string {
@@ -917,7 +1209,7 @@ type CreateGroupResponse struct {
func (x *CreateGroupResponse) Reset() {
*x = CreateGroupResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[18]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -929,7 +1221,7 @@ func (x *CreateGroupResponse) String() string {
func (*CreateGroupResponse) ProtoMessage() {}
func (x *CreateGroupResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[18]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[23]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -942,7 +1234,7 @@ func (x *CreateGroupResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use CreateGroupResponse.ProtoReflect.Descriptor instead.
func (*CreateGroupResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{18}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{23}
}
type RenameGroupRequest struct {
@@ -955,7 +1247,7 @@ type RenameGroupRequest struct {
func (x *RenameGroupRequest) Reset() {
*x = RenameGroupRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[19]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -967,7 +1259,7 @@ func (x *RenameGroupRequest) String() string {
func (*RenameGroupRequest) ProtoMessage() {}
func (x *RenameGroupRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[19]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[24]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -980,7 +1272,7 @@ func (x *RenameGroupRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use RenameGroupRequest.ProtoReflect.Descriptor instead.
func (*RenameGroupRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{19}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{24}
}
func (x *RenameGroupRequest) GetPath() []string {
@@ -1005,7 +1297,7 @@ type RenameGroupResponse struct {
func (x *RenameGroupResponse) Reset() {
*x = RenameGroupResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[20]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[25]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1017,7 +1309,7 @@ func (x *RenameGroupResponse) String() string {
func (*RenameGroupResponse) ProtoMessage() {}
func (x *RenameGroupResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[20]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[25]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1030,7 +1322,7 @@ func (x *RenameGroupResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use RenameGroupResponse.ProtoReflect.Descriptor instead.
func (*RenameGroupResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{20}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{25}
}
type DeleteGroupRequest struct {
@@ -1042,7 +1334,7 @@ type DeleteGroupRequest struct {
func (x *DeleteGroupRequest) Reset() {
*x = DeleteGroupRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[21]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[26]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1054,7 +1346,7 @@ func (x *DeleteGroupRequest) String() string {
func (*DeleteGroupRequest) ProtoMessage() {}
func (x *DeleteGroupRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[21]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[26]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1067,7 +1359,7 @@ func (x *DeleteGroupRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteGroupRequest.ProtoReflect.Descriptor instead.
func (*DeleteGroupRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{21}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{26}
}
func (x *DeleteGroupRequest) GetPath() []string {
@@ -1085,7 +1377,7 @@ type DeleteGroupResponse struct {
func (x *DeleteGroupResponse) Reset() {
*x = DeleteGroupResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[22]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[27]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1097,7 +1389,7 @@ func (x *DeleteGroupResponse) String() string {
func (*DeleteGroupResponse) ProtoMessage() {}
func (x *DeleteGroupResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[22]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[27]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1110,7 +1402,7 @@ func (x *DeleteGroupResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteGroupResponse.ProtoReflect.Descriptor instead.
func (*DeleteGroupResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{22}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{27}
}
type UpsertEntryRequest struct {
@@ -1122,7 +1414,7 @@ type UpsertEntryRequest struct {
func (x *UpsertEntryRequest) Reset() {
*x = UpsertEntryRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[23]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[28]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1134,7 +1426,7 @@ func (x *UpsertEntryRequest) String() string {
func (*UpsertEntryRequest) ProtoMessage() {}
func (x *UpsertEntryRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[23]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[28]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1147,7 +1439,7 @@ func (x *UpsertEntryRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpsertEntryRequest.ProtoReflect.Descriptor instead.
func (*UpsertEntryRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{23}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{28}
}
func (x *UpsertEntryRequest) GetEntry() *Entry {
@@ -1166,7 +1458,7 @@ type UpsertEntryResponse struct {
func (x *UpsertEntryResponse) Reset() {
*x = UpsertEntryResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[24]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[29]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1178,7 +1470,7 @@ func (x *UpsertEntryResponse) String() string {
func (*UpsertEntryResponse) ProtoMessage() {}
func (x *UpsertEntryResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[24]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[29]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1191,7 +1483,7 @@ func (x *UpsertEntryResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpsertEntryResponse.ProtoReflect.Descriptor instead.
func (*UpsertEntryResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{24}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{29}
}
func (x *UpsertEntryResponse) GetEntry() *Entry {
@@ -1210,7 +1502,7 @@ type DeleteEntryRequest struct {
func (x *DeleteEntryRequest) Reset() {
*x = DeleteEntryRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[25]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[30]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1222,7 +1514,7 @@ func (x *DeleteEntryRequest) String() string {
func (*DeleteEntryRequest) ProtoMessage() {}
func (x *DeleteEntryRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[25]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[30]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1235,7 +1527,7 @@ func (x *DeleteEntryRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteEntryRequest.ProtoReflect.Descriptor instead.
func (*DeleteEntryRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{25}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{30}
}
func (x *DeleteEntryRequest) GetId() string {
@@ -1253,7 +1545,7 @@ type DeleteEntryResponse struct {
func (x *DeleteEntryResponse) Reset() {
*x = DeleteEntryResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[26]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[31]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1265,7 +1557,7 @@ func (x *DeleteEntryResponse) String() string {
func (*DeleteEntryResponse) ProtoMessage() {}
func (x *DeleteEntryResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[26]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[31]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1278,7 +1570,7 @@ func (x *DeleteEntryResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteEntryResponse.ProtoReflect.Descriptor instead.
func (*DeleteEntryResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{26}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{31}
}
type RestoreEntryRequest struct {
@@ -1290,7 +1582,7 @@ type RestoreEntryRequest struct {
func (x *RestoreEntryRequest) Reset() {
*x = RestoreEntryRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[27]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[32]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1302,7 +1594,7 @@ func (x *RestoreEntryRequest) String() string {
func (*RestoreEntryRequest) ProtoMessage() {}
func (x *RestoreEntryRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[27]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[32]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1315,7 +1607,7 @@ func (x *RestoreEntryRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use RestoreEntryRequest.ProtoReflect.Descriptor instead.
func (*RestoreEntryRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{27}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{32}
}
func (x *RestoreEntryRequest) GetId() string {
@@ -1334,7 +1626,7 @@ type RestoreEntryResponse struct {
func (x *RestoreEntryResponse) Reset() {
*x = RestoreEntryResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[28]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[33]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1346,7 +1638,7 @@ func (x *RestoreEntryResponse) String() string {
func (*RestoreEntryResponse) ProtoMessage() {}
func (x *RestoreEntryResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[28]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[33]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1359,7 +1651,7 @@ func (x *RestoreEntryResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use RestoreEntryResponse.ProtoReflect.Descriptor instead.
func (*RestoreEntryResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{28}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{33}
}
func (x *RestoreEntryResponse) GetEntry() *Entry {
@@ -1378,7 +1670,7 @@ type ListEntryHistoryRequest struct {
func (x *ListEntryHistoryRequest) Reset() {
*x = ListEntryHistoryRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[29]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[34]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1390,7 +1682,7 @@ func (x *ListEntryHistoryRequest) String() string {
func (*ListEntryHistoryRequest) ProtoMessage() {}
func (x *ListEntryHistoryRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[29]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[34]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1403,7 +1695,7 @@ func (x *ListEntryHistoryRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListEntryHistoryRequest.ProtoReflect.Descriptor instead.
func (*ListEntryHistoryRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{29}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{34}
}
func (x *ListEntryHistoryRequest) GetId() string {
@@ -1422,7 +1714,7 @@ type ListEntryHistoryResponse struct {
func (x *ListEntryHistoryResponse) Reset() {
*x = ListEntryHistoryResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[30]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[35]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1434,7 +1726,7 @@ func (x *ListEntryHistoryResponse) String() string {
func (*ListEntryHistoryResponse) ProtoMessage() {}
func (x *ListEntryHistoryResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[30]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[35]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1447,7 +1739,7 @@ func (x *ListEntryHistoryResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListEntryHistoryResponse.ProtoReflect.Descriptor instead.
func (*ListEntryHistoryResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{30}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{35}
}
func (x *ListEntryHistoryResponse) GetEntries() []*Entry {
@@ -1467,7 +1759,7 @@ type RestoreEntryHistoryRequest struct {
func (x *RestoreEntryHistoryRequest) Reset() {
*x = RestoreEntryHistoryRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[31]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[36]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1479,7 +1771,7 @@ func (x *RestoreEntryHistoryRequest) String() string {
func (*RestoreEntryHistoryRequest) ProtoMessage() {}
func (x *RestoreEntryHistoryRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[31]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[36]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1492,7 +1784,7 @@ func (x *RestoreEntryHistoryRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use RestoreEntryHistoryRequest.ProtoReflect.Descriptor instead.
func (*RestoreEntryHistoryRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{31}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{36}
}
func (x *RestoreEntryHistoryRequest) GetId() string {
@@ -1518,7 +1810,7 @@ type RestoreEntryHistoryResponse struct {
func (x *RestoreEntryHistoryResponse) Reset() {
*x = RestoreEntryHistoryResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[32]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[37]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1530,7 +1822,7 @@ func (x *RestoreEntryHistoryResponse) String() string {
func (*RestoreEntryHistoryResponse) ProtoMessage() {}
func (x *RestoreEntryHistoryResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[32]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[37]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1543,7 +1835,7 @@ func (x *RestoreEntryHistoryResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use RestoreEntryHistoryResponse.ProtoReflect.Descriptor instead.
func (*RestoreEntryHistoryResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{32}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{37}
}
func (x *RestoreEntryHistoryResponse) GetEntry() *Entry {
@@ -1561,7 +1853,7 @@ type ListTemplatesRequest struct {
func (x *ListTemplatesRequest) Reset() {
*x = ListTemplatesRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[33]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[38]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1573,7 +1865,7 @@ func (x *ListTemplatesRequest) String() string {
func (*ListTemplatesRequest) ProtoMessage() {}
func (x *ListTemplatesRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[33]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[38]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1586,7 +1878,7 @@ func (x *ListTemplatesRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListTemplatesRequest.ProtoReflect.Descriptor instead.
func (*ListTemplatesRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{33}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{38}
}
type ListTemplatesResponse struct {
@@ -1598,7 +1890,7 @@ type ListTemplatesResponse struct {
func (x *ListTemplatesResponse) Reset() {
*x = ListTemplatesResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[34]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[39]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1610,7 +1902,7 @@ func (x *ListTemplatesResponse) String() string {
func (*ListTemplatesResponse) ProtoMessage() {}
func (x *ListTemplatesResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[34]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[39]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1623,7 +1915,7 @@ func (x *ListTemplatesResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListTemplatesResponse.ProtoReflect.Descriptor instead.
func (*ListTemplatesResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{34}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{39}
}
func (x *ListTemplatesResponse) GetTemplates() []*Entry {
@@ -1642,7 +1934,7 @@ type UpsertTemplateRequest struct {
func (x *UpsertTemplateRequest) Reset() {
*x = UpsertTemplateRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[35]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[40]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1654,7 +1946,7 @@ func (x *UpsertTemplateRequest) String() string {
func (*UpsertTemplateRequest) ProtoMessage() {}
func (x *UpsertTemplateRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[35]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[40]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1667,7 +1959,7 @@ func (x *UpsertTemplateRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpsertTemplateRequest.ProtoReflect.Descriptor instead.
func (*UpsertTemplateRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{35}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{40}
}
func (x *UpsertTemplateRequest) GetTemplate() *Entry {
@@ -1686,7 +1978,7 @@ type UpsertTemplateResponse struct {
func (x *UpsertTemplateResponse) Reset() {
*x = UpsertTemplateResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[36]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[41]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1698,7 +1990,7 @@ func (x *UpsertTemplateResponse) String() string {
func (*UpsertTemplateResponse) ProtoMessage() {}
func (x *UpsertTemplateResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[36]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[41]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1711,7 +2003,7 @@ func (x *UpsertTemplateResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpsertTemplateResponse.ProtoReflect.Descriptor instead.
func (*UpsertTemplateResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{36}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{41}
}
func (x *UpsertTemplateResponse) GetTemplate() *Entry {
@@ -1730,7 +2022,7 @@ type DeleteTemplateRequest struct {
func (x *DeleteTemplateRequest) Reset() {
*x = DeleteTemplateRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[37]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[42]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1742,7 +2034,7 @@ func (x *DeleteTemplateRequest) String() string {
func (*DeleteTemplateRequest) ProtoMessage() {}
func (x *DeleteTemplateRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[37]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[42]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1755,7 +2047,7 @@ func (x *DeleteTemplateRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteTemplateRequest.ProtoReflect.Descriptor instead.
func (*DeleteTemplateRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{37}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{42}
}
func (x *DeleteTemplateRequest) GetId() string {
@@ -1773,7 +2065,7 @@ type DeleteTemplateResponse struct {
func (x *DeleteTemplateResponse) Reset() {
*x = DeleteTemplateResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[38]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[43]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1785,7 +2077,7 @@ func (x *DeleteTemplateResponse) String() string {
func (*DeleteTemplateResponse) ProtoMessage() {}
func (x *DeleteTemplateResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[38]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[43]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1798,7 +2090,7 @@ func (x *DeleteTemplateResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteTemplateResponse.ProtoReflect.Descriptor instead.
func (*DeleteTemplateResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{38}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{43}
}
type InstantiateTemplateRequest struct {
@@ -1811,7 +2103,7 @@ type InstantiateTemplateRequest struct {
func (x *InstantiateTemplateRequest) Reset() {
*x = InstantiateTemplateRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[39]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[44]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1823,7 +2115,7 @@ func (x *InstantiateTemplateRequest) String() string {
func (*InstantiateTemplateRequest) ProtoMessage() {}
func (x *InstantiateTemplateRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[39]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[44]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1836,7 +2128,7 @@ func (x *InstantiateTemplateRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use InstantiateTemplateRequest.ProtoReflect.Descriptor instead.
func (*InstantiateTemplateRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{39}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{44}
}
func (x *InstantiateTemplateRequest) GetTemplateId() string {
@@ -1862,7 +2154,7 @@ type InstantiateTemplateResponse struct {
func (x *InstantiateTemplateResponse) Reset() {
*x = InstantiateTemplateResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[40]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[45]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1874,7 +2166,7 @@ func (x *InstantiateTemplateResponse) String() string {
func (*InstantiateTemplateResponse) ProtoMessage() {}
func (x *InstantiateTemplateResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[40]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[45]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1887,7 +2179,7 @@ func (x *InstantiateTemplateResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use InstantiateTemplateResponse.ProtoReflect.Descriptor instead.
func (*InstantiateTemplateResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{40}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{45}
}
func (x *InstantiateTemplateResponse) GetEntry() *Entry {
@@ -1906,7 +2198,7 @@ type ListAttachmentsRequest struct {
func (x *ListAttachmentsRequest) Reset() {
*x = ListAttachmentsRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[41]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[46]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1918,7 +2210,7 @@ func (x *ListAttachmentsRequest) String() string {
func (*ListAttachmentsRequest) ProtoMessage() {}
func (x *ListAttachmentsRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[41]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[46]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1931,7 +2223,7 @@ func (x *ListAttachmentsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListAttachmentsRequest.ProtoReflect.Descriptor instead.
func (*ListAttachmentsRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{41}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{46}
}
func (x *ListAttachmentsRequest) GetEntryId() string {
@@ -1950,7 +2242,7 @@ type ListAttachmentsResponse struct {
func (x *ListAttachmentsResponse) Reset() {
*x = ListAttachmentsResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[42]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[47]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1962,7 +2254,7 @@ func (x *ListAttachmentsResponse) String() string {
func (*ListAttachmentsResponse) ProtoMessage() {}
func (x *ListAttachmentsResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[42]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[47]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1975,7 +2267,7 @@ func (x *ListAttachmentsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListAttachmentsResponse.ProtoReflect.Descriptor instead.
func (*ListAttachmentsResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{42}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{47}
}
func (x *ListAttachmentsResponse) GetNames() []string {
@@ -1996,7 +2288,7 @@ type UploadAttachmentRequest struct {
func (x *UploadAttachmentRequest) Reset() {
*x = UploadAttachmentRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[43]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[48]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2008,7 +2300,7 @@ func (x *UploadAttachmentRequest) String() string {
func (*UploadAttachmentRequest) ProtoMessage() {}
func (x *UploadAttachmentRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[43]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[48]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2021,7 +2313,7 @@ func (x *UploadAttachmentRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use UploadAttachmentRequest.ProtoReflect.Descriptor instead.
func (*UploadAttachmentRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{43}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{48}
}
func (x *UploadAttachmentRequest) GetEntryId() string {
@@ -2053,7 +2345,7 @@ type UploadAttachmentResponse struct {
func (x *UploadAttachmentResponse) Reset() {
*x = UploadAttachmentResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[44]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[49]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2065,7 +2357,7 @@ func (x *UploadAttachmentResponse) String() string {
func (*UploadAttachmentResponse) ProtoMessage() {}
func (x *UploadAttachmentResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[44]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[49]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2078,7 +2370,7 @@ func (x *UploadAttachmentResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use UploadAttachmentResponse.ProtoReflect.Descriptor instead.
func (*UploadAttachmentResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{44}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{49}
}
type DownloadAttachmentRequest struct {
@@ -2091,7 +2383,7 @@ type DownloadAttachmentRequest struct {
func (x *DownloadAttachmentRequest) Reset() {
*x = DownloadAttachmentRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[45]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[50]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2103,7 +2395,7 @@ func (x *DownloadAttachmentRequest) String() string {
func (*DownloadAttachmentRequest) ProtoMessage() {}
func (x *DownloadAttachmentRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[45]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[50]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2116,7 +2408,7 @@ func (x *DownloadAttachmentRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DownloadAttachmentRequest.ProtoReflect.Descriptor instead.
func (*DownloadAttachmentRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{45}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{50}
}
func (x *DownloadAttachmentRequest) GetEntryId() string {
@@ -2142,7 +2434,7 @@ type DownloadAttachmentResponse struct {
func (x *DownloadAttachmentResponse) Reset() {
*x = DownloadAttachmentResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[46]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[51]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2154,7 +2446,7 @@ func (x *DownloadAttachmentResponse) String() string {
func (*DownloadAttachmentResponse) ProtoMessage() {}
func (x *DownloadAttachmentResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[46]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[51]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2167,7 +2459,7 @@ func (x *DownloadAttachmentResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use DownloadAttachmentResponse.ProtoReflect.Descriptor instead.
func (*DownloadAttachmentResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{46}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{51}
}
func (x *DownloadAttachmentResponse) GetContent() []byte {
@@ -2187,7 +2479,7 @@ type DeleteAttachmentRequest struct {
func (x *DeleteAttachmentRequest) Reset() {
*x = DeleteAttachmentRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[47]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[52]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2199,7 +2491,7 @@ func (x *DeleteAttachmentRequest) String() string {
func (*DeleteAttachmentRequest) ProtoMessage() {}
func (x *DeleteAttachmentRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[47]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[52]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2212,7 +2504,7 @@ func (x *DeleteAttachmentRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteAttachmentRequest.ProtoReflect.Descriptor instead.
func (*DeleteAttachmentRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{47}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{52}
}
func (x *DeleteAttachmentRequest) GetEntryId() string {
@@ -2237,7 +2529,7 @@ type DeleteAttachmentResponse struct {
func (x *DeleteAttachmentResponse) Reset() {
*x = DeleteAttachmentResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[48]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[53]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2249,7 +2541,7 @@ func (x *DeleteAttachmentResponse) String() string {
func (*DeleteAttachmentResponse) ProtoMessage() {}
func (x *DeleteAttachmentResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[48]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[53]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2262,7 +2554,7 @@ func (x *DeleteAttachmentResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteAttachmentResponse.ProtoReflect.Descriptor instead.
func (*DeleteAttachmentResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{48}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{53}
}
type CopyEntryFieldRequest struct {
@@ -2275,7 +2567,7 @@ type CopyEntryFieldRequest struct {
func (x *CopyEntryFieldRequest) Reset() {
*x = CopyEntryFieldRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[49]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[54]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2287,7 +2579,7 @@ func (x *CopyEntryFieldRequest) String() string {
func (*CopyEntryFieldRequest) ProtoMessage() {}
func (x *CopyEntryFieldRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[49]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[54]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2300,7 +2592,7 @@ func (x *CopyEntryFieldRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use CopyEntryFieldRequest.ProtoReflect.Descriptor instead.
func (*CopyEntryFieldRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{49}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{54}
}
func (x *CopyEntryFieldRequest) GetId() string {
@@ -2325,7 +2617,7 @@ type CopyEntryFieldResponse struct {
func (x *CopyEntryFieldResponse) Reset() {
*x = CopyEntryFieldResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[50]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[55]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2337,7 +2629,7 @@ func (x *CopyEntryFieldResponse) String() string {
func (*CopyEntryFieldResponse) ProtoMessage() {}
func (x *CopyEntryFieldResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[50]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[55]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2350,7 +2642,7 @@ func (x *CopyEntryFieldResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use CopyEntryFieldResponse.ProtoReflect.Descriptor instead.
func (*CopyEntryFieldResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{50}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{55}
}
type GeneratePasswordRequest struct {
@@ -2362,7 +2654,7 @@ type GeneratePasswordRequest struct {
func (x *GeneratePasswordRequest) Reset() {
*x = GeneratePasswordRequest{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[51]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[56]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2374,7 +2666,7 @@ func (x *GeneratePasswordRequest) String() string {
func (*GeneratePasswordRequest) ProtoMessage() {}
func (x *GeneratePasswordRequest) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[51]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[56]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2387,7 +2679,7 @@ func (x *GeneratePasswordRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GeneratePasswordRequest.ProtoReflect.Descriptor instead.
func (*GeneratePasswordRequest) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{51}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{56}
}
func (x *GeneratePasswordRequest) GetProfile() string {
@@ -2406,7 +2698,7 @@ type GeneratePasswordResponse struct {
func (x *GeneratePasswordResponse) Reset() {
*x = GeneratePasswordResponse{}
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[52]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[57]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2418,7 +2710,7 @@ func (x *GeneratePasswordResponse) String() string {
func (*GeneratePasswordResponse) ProtoMessage() {}
func (x *GeneratePasswordResponse) ProtoReflect() protoreflect.Message {
- mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[52]
+ mi := &file_proto_keepassgo_v1_keepassgo_proto_msgTypes[57]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2431,7 +2723,7 @@ func (x *GeneratePasswordResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use GeneratePasswordResponse.ProtoReflect.Descriptor instead.
func (*GeneratePasswordResponse) Descriptor() ([]byte, []int) {
- return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{52}
+ return file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP(), []int{57}
}
func (x *GeneratePasswordResponse) GetPassword() string {
@@ -2472,7 +2764,26 @@ const file_proto_keepassgo_v1_keepassgo_proto_rawDesc = "" +
"\x12UnlockVaultRequest\x12\x1a\n" +
"\bpassword\x18\x01 \x01(\tR\bpassword\x12\"\n" +
"\rkey_file_data\x18\x02 \x01(\fR\vkeyFileData\"\x15\n" +
- "\x13UnlockVaultResponse\">\n" +
+ "\x13UnlockVaultResponse\"5\n" +
+ "\x18FindBrowserLoginsRequest\x12\x19\n" +
+ "\bpage_url\x18\x01 \x01(\tR\apageUrl\"\x95\x01\n" +
+ "\x11BrowserLoginMatch\x12\x0e\n" +
+ "\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n" +
+ "\x05title\x18\x02 \x01(\tR\x05title\x12\x1a\n" +
+ "\busername\x18\x03 \x01(\tR\busername\x12\x10\n" +
+ "\x03url\x18\x04 \x01(\tR\x03url\x12\x12\n" +
+ "\x04path\x18\x05 \x03(\tR\x04path\x12\x18\n" +
+ "\aquality\x18\x06 \x01(\tR\aquality\"V\n" +
+ "\x19FindBrowserLoginsResponse\x129\n" +
+ "\amatches\x18\x01 \x03(\v2\x1f.keepassgo.v1.BrowserLoginMatchR\amatches\"H\n" +
+ "\x1bGetBrowserCredentialRequest\x12\x0e\n" +
+ "\x02id\x18\x01 \x01(\tR\x02id\x12\x19\n" +
+ "\bpage_url\x18\x02 \x01(\tR\apageUrl\"x\n" +
+ "\x1cGetBrowserCredentialResponse\x12\x0e\n" +
+ "\x02id\x18\x01 \x01(\tR\x02id\x12\x1a\n" +
+ "\busername\x18\x02 \x01(\tR\busername\x12\x1a\n" +
+ "\bpassword\x18\x03 \x01(\tR\bpassword\x12\x10\n" +
+ "\x03url\x18\x04 \x01(\tR\x03url\">\n" +
"\x12ListEntriesRequest\x12\x12\n" +
"\x04path\x18\x01 \x03(\tR\x04path\x12\x14\n" +
"\x05query\x18\x02 \x01(\tR\x05query\"\xa9\x02\n" +
@@ -2568,14 +2879,16 @@ const file_proto_keepassgo_v1_keepassgo_proto_rawDesc = "" +
"\x17GeneratePasswordRequest\x12\x18\n" +
"\aprofile\x18\x01 \x01(\tR\aprofile\"6\n" +
"\x18GeneratePasswordResponse\x12\x1a\n" +
- "\bpassword\x18\x01 \x01(\tR\bpassword2\xcd\x12\n" +
+ "\bpassword\x18\x01 \x01(\tR\bpassword2\xa2\x14\n" +
"\fVaultService\x12a\n" +
"\x10GetSessionStatus\x12%.keepassgo.v1.GetSessionStatusRequest\x1a&.keepassgo.v1.GetSessionStatusResponse\x12L\n" +
"\tOpenVault\x12\x1e.keepassgo.v1.OpenVaultRequest\x1a\x1f.keepassgo.v1.OpenVaultResponse\x12^\n" +
"\x0fOpenRemoteVault\x12$.keepassgo.v1.OpenRemoteVaultRequest\x1a%.keepassgo.v1.OpenRemoteVaultResponse\x12L\n" +
"\tSaveVault\x12\x1e.keepassgo.v1.SaveVaultRequest\x1a\x1f.keepassgo.v1.SaveVaultResponse\x12L\n" +
"\tLockVault\x12\x1e.keepassgo.v1.LockVaultRequest\x1a\x1f.keepassgo.v1.LockVaultResponse\x12R\n" +
- "\vUnlockVault\x12 .keepassgo.v1.UnlockVaultRequest\x1a!.keepassgo.v1.UnlockVaultResponse\x12R\n" +
+ "\vUnlockVault\x12 .keepassgo.v1.UnlockVaultRequest\x1a!.keepassgo.v1.UnlockVaultResponse\x12d\n" +
+ "\x11FindBrowserLogins\x12&.keepassgo.v1.FindBrowserLoginsRequest\x1a'.keepassgo.v1.FindBrowserLoginsResponse\x12m\n" +
+ "\x14GetBrowserCredential\x12).keepassgo.v1.GetBrowserCredentialRequest\x1a*.keepassgo.v1.GetBrowserCredentialResponse\x12R\n" +
"\vListEntries\x12 .keepassgo.v1.ListEntriesRequest\x1a!.keepassgo.v1.ListEntriesResponse\x12O\n" +
"\n" +
"ListGroups\x12\x1f.keepassgo.v1.ListGroupsRequest\x1a .keepassgo.v1.ListGroupsResponse\x12R\n" +
@@ -2610,133 +2923,143 @@ func file_proto_keepassgo_v1_keepassgo_proto_rawDescGZIP() []byte {
return file_proto_keepassgo_v1_keepassgo_proto_rawDescData
}
-var file_proto_keepassgo_v1_keepassgo_proto_msgTypes = make([]protoimpl.MessageInfo, 54)
+var file_proto_keepassgo_v1_keepassgo_proto_msgTypes = make([]protoimpl.MessageInfo, 59)
var file_proto_keepassgo_v1_keepassgo_proto_goTypes = []any{
- (*GetSessionStatusRequest)(nil), // 0: keepassgo.v1.GetSessionStatusRequest
- (*GetSessionStatusResponse)(nil), // 1: keepassgo.v1.GetSessionStatusResponse
- (*OpenVaultRequest)(nil), // 2: keepassgo.v1.OpenVaultRequest
- (*OpenVaultResponse)(nil), // 3: keepassgo.v1.OpenVaultResponse
- (*OpenRemoteVaultRequest)(nil), // 4: keepassgo.v1.OpenRemoteVaultRequest
- (*OpenRemoteVaultResponse)(nil), // 5: keepassgo.v1.OpenRemoteVaultResponse
- (*SaveVaultRequest)(nil), // 6: keepassgo.v1.SaveVaultRequest
- (*SaveVaultResponse)(nil), // 7: keepassgo.v1.SaveVaultResponse
- (*LockVaultRequest)(nil), // 8: keepassgo.v1.LockVaultRequest
- (*LockVaultResponse)(nil), // 9: keepassgo.v1.LockVaultResponse
- (*UnlockVaultRequest)(nil), // 10: keepassgo.v1.UnlockVaultRequest
- (*UnlockVaultResponse)(nil), // 11: keepassgo.v1.UnlockVaultResponse
- (*ListEntriesRequest)(nil), // 12: keepassgo.v1.ListEntriesRequest
- (*Entry)(nil), // 13: keepassgo.v1.Entry
- (*ListEntriesResponse)(nil), // 14: keepassgo.v1.ListEntriesResponse
- (*ListGroupsRequest)(nil), // 15: keepassgo.v1.ListGroupsRequest
- (*ListGroupsResponse)(nil), // 16: keepassgo.v1.ListGroupsResponse
- (*CreateGroupRequest)(nil), // 17: keepassgo.v1.CreateGroupRequest
- (*CreateGroupResponse)(nil), // 18: keepassgo.v1.CreateGroupResponse
- (*RenameGroupRequest)(nil), // 19: keepassgo.v1.RenameGroupRequest
- (*RenameGroupResponse)(nil), // 20: keepassgo.v1.RenameGroupResponse
- (*DeleteGroupRequest)(nil), // 21: keepassgo.v1.DeleteGroupRequest
- (*DeleteGroupResponse)(nil), // 22: keepassgo.v1.DeleteGroupResponse
- (*UpsertEntryRequest)(nil), // 23: keepassgo.v1.UpsertEntryRequest
- (*UpsertEntryResponse)(nil), // 24: keepassgo.v1.UpsertEntryResponse
- (*DeleteEntryRequest)(nil), // 25: keepassgo.v1.DeleteEntryRequest
- (*DeleteEntryResponse)(nil), // 26: keepassgo.v1.DeleteEntryResponse
- (*RestoreEntryRequest)(nil), // 27: keepassgo.v1.RestoreEntryRequest
- (*RestoreEntryResponse)(nil), // 28: keepassgo.v1.RestoreEntryResponse
- (*ListEntryHistoryRequest)(nil), // 29: keepassgo.v1.ListEntryHistoryRequest
- (*ListEntryHistoryResponse)(nil), // 30: keepassgo.v1.ListEntryHistoryResponse
- (*RestoreEntryHistoryRequest)(nil), // 31: keepassgo.v1.RestoreEntryHistoryRequest
- (*RestoreEntryHistoryResponse)(nil), // 32: keepassgo.v1.RestoreEntryHistoryResponse
- (*ListTemplatesRequest)(nil), // 33: keepassgo.v1.ListTemplatesRequest
- (*ListTemplatesResponse)(nil), // 34: keepassgo.v1.ListTemplatesResponse
- (*UpsertTemplateRequest)(nil), // 35: keepassgo.v1.UpsertTemplateRequest
- (*UpsertTemplateResponse)(nil), // 36: keepassgo.v1.UpsertTemplateResponse
- (*DeleteTemplateRequest)(nil), // 37: keepassgo.v1.DeleteTemplateRequest
- (*DeleteTemplateResponse)(nil), // 38: keepassgo.v1.DeleteTemplateResponse
- (*InstantiateTemplateRequest)(nil), // 39: keepassgo.v1.InstantiateTemplateRequest
- (*InstantiateTemplateResponse)(nil), // 40: keepassgo.v1.InstantiateTemplateResponse
- (*ListAttachmentsRequest)(nil), // 41: keepassgo.v1.ListAttachmentsRequest
- (*ListAttachmentsResponse)(nil), // 42: keepassgo.v1.ListAttachmentsResponse
- (*UploadAttachmentRequest)(nil), // 43: keepassgo.v1.UploadAttachmentRequest
- (*UploadAttachmentResponse)(nil), // 44: keepassgo.v1.UploadAttachmentResponse
- (*DownloadAttachmentRequest)(nil), // 45: keepassgo.v1.DownloadAttachmentRequest
- (*DownloadAttachmentResponse)(nil), // 46: keepassgo.v1.DownloadAttachmentResponse
- (*DeleteAttachmentRequest)(nil), // 47: keepassgo.v1.DeleteAttachmentRequest
- (*DeleteAttachmentResponse)(nil), // 48: keepassgo.v1.DeleteAttachmentResponse
- (*CopyEntryFieldRequest)(nil), // 49: keepassgo.v1.CopyEntryFieldRequest
- (*CopyEntryFieldResponse)(nil), // 50: keepassgo.v1.CopyEntryFieldResponse
- (*GeneratePasswordRequest)(nil), // 51: keepassgo.v1.GeneratePasswordRequest
- (*GeneratePasswordResponse)(nil), // 52: keepassgo.v1.GeneratePasswordResponse
- nil, // 53: keepassgo.v1.Entry.FieldsEntry
+ (*GetSessionStatusRequest)(nil), // 0: keepassgo.v1.GetSessionStatusRequest
+ (*GetSessionStatusResponse)(nil), // 1: keepassgo.v1.GetSessionStatusResponse
+ (*OpenVaultRequest)(nil), // 2: keepassgo.v1.OpenVaultRequest
+ (*OpenVaultResponse)(nil), // 3: keepassgo.v1.OpenVaultResponse
+ (*OpenRemoteVaultRequest)(nil), // 4: keepassgo.v1.OpenRemoteVaultRequest
+ (*OpenRemoteVaultResponse)(nil), // 5: keepassgo.v1.OpenRemoteVaultResponse
+ (*SaveVaultRequest)(nil), // 6: keepassgo.v1.SaveVaultRequest
+ (*SaveVaultResponse)(nil), // 7: keepassgo.v1.SaveVaultResponse
+ (*LockVaultRequest)(nil), // 8: keepassgo.v1.LockVaultRequest
+ (*LockVaultResponse)(nil), // 9: keepassgo.v1.LockVaultResponse
+ (*UnlockVaultRequest)(nil), // 10: keepassgo.v1.UnlockVaultRequest
+ (*UnlockVaultResponse)(nil), // 11: keepassgo.v1.UnlockVaultResponse
+ (*FindBrowserLoginsRequest)(nil), // 12: keepassgo.v1.FindBrowserLoginsRequest
+ (*BrowserLoginMatch)(nil), // 13: keepassgo.v1.BrowserLoginMatch
+ (*FindBrowserLoginsResponse)(nil), // 14: keepassgo.v1.FindBrowserLoginsResponse
+ (*GetBrowserCredentialRequest)(nil), // 15: keepassgo.v1.GetBrowserCredentialRequest
+ (*GetBrowserCredentialResponse)(nil), // 16: keepassgo.v1.GetBrowserCredentialResponse
+ (*ListEntriesRequest)(nil), // 17: keepassgo.v1.ListEntriesRequest
+ (*Entry)(nil), // 18: keepassgo.v1.Entry
+ (*ListEntriesResponse)(nil), // 19: keepassgo.v1.ListEntriesResponse
+ (*ListGroupsRequest)(nil), // 20: keepassgo.v1.ListGroupsRequest
+ (*ListGroupsResponse)(nil), // 21: keepassgo.v1.ListGroupsResponse
+ (*CreateGroupRequest)(nil), // 22: keepassgo.v1.CreateGroupRequest
+ (*CreateGroupResponse)(nil), // 23: keepassgo.v1.CreateGroupResponse
+ (*RenameGroupRequest)(nil), // 24: keepassgo.v1.RenameGroupRequest
+ (*RenameGroupResponse)(nil), // 25: keepassgo.v1.RenameGroupResponse
+ (*DeleteGroupRequest)(nil), // 26: keepassgo.v1.DeleteGroupRequest
+ (*DeleteGroupResponse)(nil), // 27: keepassgo.v1.DeleteGroupResponse
+ (*UpsertEntryRequest)(nil), // 28: keepassgo.v1.UpsertEntryRequest
+ (*UpsertEntryResponse)(nil), // 29: keepassgo.v1.UpsertEntryResponse
+ (*DeleteEntryRequest)(nil), // 30: keepassgo.v1.DeleteEntryRequest
+ (*DeleteEntryResponse)(nil), // 31: keepassgo.v1.DeleteEntryResponse
+ (*RestoreEntryRequest)(nil), // 32: keepassgo.v1.RestoreEntryRequest
+ (*RestoreEntryResponse)(nil), // 33: keepassgo.v1.RestoreEntryResponse
+ (*ListEntryHistoryRequest)(nil), // 34: keepassgo.v1.ListEntryHistoryRequest
+ (*ListEntryHistoryResponse)(nil), // 35: keepassgo.v1.ListEntryHistoryResponse
+ (*RestoreEntryHistoryRequest)(nil), // 36: keepassgo.v1.RestoreEntryHistoryRequest
+ (*RestoreEntryHistoryResponse)(nil), // 37: keepassgo.v1.RestoreEntryHistoryResponse
+ (*ListTemplatesRequest)(nil), // 38: keepassgo.v1.ListTemplatesRequest
+ (*ListTemplatesResponse)(nil), // 39: keepassgo.v1.ListTemplatesResponse
+ (*UpsertTemplateRequest)(nil), // 40: keepassgo.v1.UpsertTemplateRequest
+ (*UpsertTemplateResponse)(nil), // 41: keepassgo.v1.UpsertTemplateResponse
+ (*DeleteTemplateRequest)(nil), // 42: keepassgo.v1.DeleteTemplateRequest
+ (*DeleteTemplateResponse)(nil), // 43: keepassgo.v1.DeleteTemplateResponse
+ (*InstantiateTemplateRequest)(nil), // 44: keepassgo.v1.InstantiateTemplateRequest
+ (*InstantiateTemplateResponse)(nil), // 45: keepassgo.v1.InstantiateTemplateResponse
+ (*ListAttachmentsRequest)(nil), // 46: keepassgo.v1.ListAttachmentsRequest
+ (*ListAttachmentsResponse)(nil), // 47: keepassgo.v1.ListAttachmentsResponse
+ (*UploadAttachmentRequest)(nil), // 48: keepassgo.v1.UploadAttachmentRequest
+ (*UploadAttachmentResponse)(nil), // 49: keepassgo.v1.UploadAttachmentResponse
+ (*DownloadAttachmentRequest)(nil), // 50: keepassgo.v1.DownloadAttachmentRequest
+ (*DownloadAttachmentResponse)(nil), // 51: keepassgo.v1.DownloadAttachmentResponse
+ (*DeleteAttachmentRequest)(nil), // 52: keepassgo.v1.DeleteAttachmentRequest
+ (*DeleteAttachmentResponse)(nil), // 53: keepassgo.v1.DeleteAttachmentResponse
+ (*CopyEntryFieldRequest)(nil), // 54: keepassgo.v1.CopyEntryFieldRequest
+ (*CopyEntryFieldResponse)(nil), // 55: keepassgo.v1.CopyEntryFieldResponse
+ (*GeneratePasswordRequest)(nil), // 56: keepassgo.v1.GeneratePasswordRequest
+ (*GeneratePasswordResponse)(nil), // 57: keepassgo.v1.GeneratePasswordResponse
+ nil, // 58: keepassgo.v1.Entry.FieldsEntry
}
var file_proto_keepassgo_v1_keepassgo_proto_depIdxs = []int32{
- 53, // 0: keepassgo.v1.Entry.fields:type_name -> keepassgo.v1.Entry.FieldsEntry
- 13, // 1: keepassgo.v1.ListEntriesResponse.entries:type_name -> keepassgo.v1.Entry
- 13, // 2: keepassgo.v1.UpsertEntryRequest.entry:type_name -> keepassgo.v1.Entry
- 13, // 3: keepassgo.v1.UpsertEntryResponse.entry:type_name -> keepassgo.v1.Entry
- 13, // 4: keepassgo.v1.RestoreEntryResponse.entry:type_name -> keepassgo.v1.Entry
- 13, // 5: keepassgo.v1.ListEntryHistoryResponse.entries:type_name -> keepassgo.v1.Entry
- 13, // 6: keepassgo.v1.RestoreEntryHistoryResponse.entry:type_name -> keepassgo.v1.Entry
- 13, // 7: keepassgo.v1.ListTemplatesResponse.templates:type_name -> keepassgo.v1.Entry
- 13, // 8: keepassgo.v1.UpsertTemplateRequest.template:type_name -> keepassgo.v1.Entry
- 13, // 9: keepassgo.v1.UpsertTemplateResponse.template:type_name -> keepassgo.v1.Entry
- 13, // 10: keepassgo.v1.InstantiateTemplateRequest.overrides:type_name -> keepassgo.v1.Entry
- 13, // 11: keepassgo.v1.InstantiateTemplateResponse.entry:type_name -> keepassgo.v1.Entry
- 0, // 12: keepassgo.v1.VaultService.GetSessionStatus:input_type -> keepassgo.v1.GetSessionStatusRequest
- 2, // 13: keepassgo.v1.VaultService.OpenVault:input_type -> keepassgo.v1.OpenVaultRequest
- 4, // 14: keepassgo.v1.VaultService.OpenRemoteVault:input_type -> keepassgo.v1.OpenRemoteVaultRequest
- 6, // 15: keepassgo.v1.VaultService.SaveVault:input_type -> keepassgo.v1.SaveVaultRequest
- 8, // 16: keepassgo.v1.VaultService.LockVault:input_type -> keepassgo.v1.LockVaultRequest
- 10, // 17: keepassgo.v1.VaultService.UnlockVault:input_type -> keepassgo.v1.UnlockVaultRequest
- 12, // 18: keepassgo.v1.VaultService.ListEntries:input_type -> keepassgo.v1.ListEntriesRequest
- 15, // 19: keepassgo.v1.VaultService.ListGroups:input_type -> keepassgo.v1.ListGroupsRequest
- 17, // 20: keepassgo.v1.VaultService.CreateGroup:input_type -> keepassgo.v1.CreateGroupRequest
- 19, // 21: keepassgo.v1.VaultService.RenameGroup:input_type -> keepassgo.v1.RenameGroupRequest
- 21, // 22: keepassgo.v1.VaultService.DeleteGroup:input_type -> keepassgo.v1.DeleteGroupRequest
- 23, // 23: keepassgo.v1.VaultService.UpsertEntry:input_type -> keepassgo.v1.UpsertEntryRequest
- 25, // 24: keepassgo.v1.VaultService.DeleteEntry:input_type -> keepassgo.v1.DeleteEntryRequest
- 27, // 25: keepassgo.v1.VaultService.RestoreEntry:input_type -> keepassgo.v1.RestoreEntryRequest
- 29, // 26: keepassgo.v1.VaultService.ListEntryHistory:input_type -> keepassgo.v1.ListEntryHistoryRequest
- 31, // 27: keepassgo.v1.VaultService.RestoreEntryHistory:input_type -> keepassgo.v1.RestoreEntryHistoryRequest
- 33, // 28: keepassgo.v1.VaultService.ListTemplates:input_type -> keepassgo.v1.ListTemplatesRequest
- 35, // 29: keepassgo.v1.VaultService.UpsertTemplate:input_type -> keepassgo.v1.UpsertTemplateRequest
- 37, // 30: keepassgo.v1.VaultService.DeleteTemplate:input_type -> keepassgo.v1.DeleteTemplateRequest
- 39, // 31: keepassgo.v1.VaultService.InstantiateTemplate:input_type -> keepassgo.v1.InstantiateTemplateRequest
- 41, // 32: keepassgo.v1.VaultService.ListAttachments:input_type -> keepassgo.v1.ListAttachmentsRequest
- 43, // 33: keepassgo.v1.VaultService.UploadAttachment:input_type -> keepassgo.v1.UploadAttachmentRequest
- 45, // 34: keepassgo.v1.VaultService.DownloadAttachment:input_type -> keepassgo.v1.DownloadAttachmentRequest
- 47, // 35: keepassgo.v1.VaultService.DeleteAttachment:input_type -> keepassgo.v1.DeleteAttachmentRequest
- 49, // 36: keepassgo.v1.VaultService.CopyEntryField:input_type -> keepassgo.v1.CopyEntryFieldRequest
- 51, // 37: keepassgo.v1.VaultService.GeneratePassword:input_type -> keepassgo.v1.GeneratePasswordRequest
- 1, // 38: keepassgo.v1.VaultService.GetSessionStatus:output_type -> keepassgo.v1.GetSessionStatusResponse
- 3, // 39: keepassgo.v1.VaultService.OpenVault:output_type -> keepassgo.v1.OpenVaultResponse
- 5, // 40: keepassgo.v1.VaultService.OpenRemoteVault:output_type -> keepassgo.v1.OpenRemoteVaultResponse
- 7, // 41: keepassgo.v1.VaultService.SaveVault:output_type -> keepassgo.v1.SaveVaultResponse
- 9, // 42: keepassgo.v1.VaultService.LockVault:output_type -> keepassgo.v1.LockVaultResponse
- 11, // 43: keepassgo.v1.VaultService.UnlockVault:output_type -> keepassgo.v1.UnlockVaultResponse
- 14, // 44: keepassgo.v1.VaultService.ListEntries:output_type -> keepassgo.v1.ListEntriesResponse
- 16, // 45: keepassgo.v1.VaultService.ListGroups:output_type -> keepassgo.v1.ListGroupsResponse
- 18, // 46: keepassgo.v1.VaultService.CreateGroup:output_type -> keepassgo.v1.CreateGroupResponse
- 20, // 47: keepassgo.v1.VaultService.RenameGroup:output_type -> keepassgo.v1.RenameGroupResponse
- 22, // 48: keepassgo.v1.VaultService.DeleteGroup:output_type -> keepassgo.v1.DeleteGroupResponse
- 24, // 49: keepassgo.v1.VaultService.UpsertEntry:output_type -> keepassgo.v1.UpsertEntryResponse
- 26, // 50: keepassgo.v1.VaultService.DeleteEntry:output_type -> keepassgo.v1.DeleteEntryResponse
- 28, // 51: keepassgo.v1.VaultService.RestoreEntry:output_type -> keepassgo.v1.RestoreEntryResponse
- 30, // 52: keepassgo.v1.VaultService.ListEntryHistory:output_type -> keepassgo.v1.ListEntryHistoryResponse
- 32, // 53: keepassgo.v1.VaultService.RestoreEntryHistory:output_type -> keepassgo.v1.RestoreEntryHistoryResponse
- 34, // 54: keepassgo.v1.VaultService.ListTemplates:output_type -> keepassgo.v1.ListTemplatesResponse
- 36, // 55: keepassgo.v1.VaultService.UpsertTemplate:output_type -> keepassgo.v1.UpsertTemplateResponse
- 38, // 56: keepassgo.v1.VaultService.DeleteTemplate:output_type -> keepassgo.v1.DeleteTemplateResponse
- 40, // 57: keepassgo.v1.VaultService.InstantiateTemplate:output_type -> keepassgo.v1.InstantiateTemplateResponse
- 42, // 58: keepassgo.v1.VaultService.ListAttachments:output_type -> keepassgo.v1.ListAttachmentsResponse
- 44, // 59: keepassgo.v1.VaultService.UploadAttachment:output_type -> keepassgo.v1.UploadAttachmentResponse
- 46, // 60: keepassgo.v1.VaultService.DownloadAttachment:output_type -> keepassgo.v1.DownloadAttachmentResponse
- 48, // 61: keepassgo.v1.VaultService.DeleteAttachment:output_type -> keepassgo.v1.DeleteAttachmentResponse
- 50, // 62: keepassgo.v1.VaultService.CopyEntryField:output_type -> keepassgo.v1.CopyEntryFieldResponse
- 52, // 63: keepassgo.v1.VaultService.GeneratePassword:output_type -> keepassgo.v1.GeneratePasswordResponse
- 38, // [38:64] is the sub-list for method output_type
- 12, // [12:38] is the sub-list for method input_type
- 12, // [12:12] is the sub-list for extension type_name
- 12, // [12:12] is the sub-list for extension extendee
- 0, // [0:12] is the sub-list for field type_name
+ 13, // 0: keepassgo.v1.FindBrowserLoginsResponse.matches:type_name -> keepassgo.v1.BrowserLoginMatch
+ 58, // 1: keepassgo.v1.Entry.fields:type_name -> keepassgo.v1.Entry.FieldsEntry
+ 18, // 2: keepassgo.v1.ListEntriesResponse.entries:type_name -> keepassgo.v1.Entry
+ 18, // 3: keepassgo.v1.UpsertEntryRequest.entry:type_name -> keepassgo.v1.Entry
+ 18, // 4: keepassgo.v1.UpsertEntryResponse.entry:type_name -> keepassgo.v1.Entry
+ 18, // 5: keepassgo.v1.RestoreEntryResponse.entry:type_name -> keepassgo.v1.Entry
+ 18, // 6: keepassgo.v1.ListEntryHistoryResponse.entries:type_name -> keepassgo.v1.Entry
+ 18, // 7: keepassgo.v1.RestoreEntryHistoryResponse.entry:type_name -> keepassgo.v1.Entry
+ 18, // 8: keepassgo.v1.ListTemplatesResponse.templates:type_name -> keepassgo.v1.Entry
+ 18, // 9: keepassgo.v1.UpsertTemplateRequest.template:type_name -> keepassgo.v1.Entry
+ 18, // 10: keepassgo.v1.UpsertTemplateResponse.template:type_name -> keepassgo.v1.Entry
+ 18, // 11: keepassgo.v1.InstantiateTemplateRequest.overrides:type_name -> keepassgo.v1.Entry
+ 18, // 12: keepassgo.v1.InstantiateTemplateResponse.entry:type_name -> keepassgo.v1.Entry
+ 0, // 13: keepassgo.v1.VaultService.GetSessionStatus:input_type -> keepassgo.v1.GetSessionStatusRequest
+ 2, // 14: keepassgo.v1.VaultService.OpenVault:input_type -> keepassgo.v1.OpenVaultRequest
+ 4, // 15: keepassgo.v1.VaultService.OpenRemoteVault:input_type -> keepassgo.v1.OpenRemoteVaultRequest
+ 6, // 16: keepassgo.v1.VaultService.SaveVault:input_type -> keepassgo.v1.SaveVaultRequest
+ 8, // 17: keepassgo.v1.VaultService.LockVault:input_type -> keepassgo.v1.LockVaultRequest
+ 10, // 18: keepassgo.v1.VaultService.UnlockVault:input_type -> keepassgo.v1.UnlockVaultRequest
+ 12, // 19: keepassgo.v1.VaultService.FindBrowserLogins:input_type -> keepassgo.v1.FindBrowserLoginsRequest
+ 15, // 20: keepassgo.v1.VaultService.GetBrowserCredential:input_type -> keepassgo.v1.GetBrowserCredentialRequest
+ 17, // 21: keepassgo.v1.VaultService.ListEntries:input_type -> keepassgo.v1.ListEntriesRequest
+ 20, // 22: keepassgo.v1.VaultService.ListGroups:input_type -> keepassgo.v1.ListGroupsRequest
+ 22, // 23: keepassgo.v1.VaultService.CreateGroup:input_type -> keepassgo.v1.CreateGroupRequest
+ 24, // 24: keepassgo.v1.VaultService.RenameGroup:input_type -> keepassgo.v1.RenameGroupRequest
+ 26, // 25: keepassgo.v1.VaultService.DeleteGroup:input_type -> keepassgo.v1.DeleteGroupRequest
+ 28, // 26: keepassgo.v1.VaultService.UpsertEntry:input_type -> keepassgo.v1.UpsertEntryRequest
+ 30, // 27: keepassgo.v1.VaultService.DeleteEntry:input_type -> keepassgo.v1.DeleteEntryRequest
+ 32, // 28: keepassgo.v1.VaultService.RestoreEntry:input_type -> keepassgo.v1.RestoreEntryRequest
+ 34, // 29: keepassgo.v1.VaultService.ListEntryHistory:input_type -> keepassgo.v1.ListEntryHistoryRequest
+ 36, // 30: keepassgo.v1.VaultService.RestoreEntryHistory:input_type -> keepassgo.v1.RestoreEntryHistoryRequest
+ 38, // 31: keepassgo.v1.VaultService.ListTemplates:input_type -> keepassgo.v1.ListTemplatesRequest
+ 40, // 32: keepassgo.v1.VaultService.UpsertTemplate:input_type -> keepassgo.v1.UpsertTemplateRequest
+ 42, // 33: keepassgo.v1.VaultService.DeleteTemplate:input_type -> keepassgo.v1.DeleteTemplateRequest
+ 44, // 34: keepassgo.v1.VaultService.InstantiateTemplate:input_type -> keepassgo.v1.InstantiateTemplateRequest
+ 46, // 35: keepassgo.v1.VaultService.ListAttachments:input_type -> keepassgo.v1.ListAttachmentsRequest
+ 48, // 36: keepassgo.v1.VaultService.UploadAttachment:input_type -> keepassgo.v1.UploadAttachmentRequest
+ 50, // 37: keepassgo.v1.VaultService.DownloadAttachment:input_type -> keepassgo.v1.DownloadAttachmentRequest
+ 52, // 38: keepassgo.v1.VaultService.DeleteAttachment:input_type -> keepassgo.v1.DeleteAttachmentRequest
+ 54, // 39: keepassgo.v1.VaultService.CopyEntryField:input_type -> keepassgo.v1.CopyEntryFieldRequest
+ 56, // 40: keepassgo.v1.VaultService.GeneratePassword:input_type -> keepassgo.v1.GeneratePasswordRequest
+ 1, // 41: keepassgo.v1.VaultService.GetSessionStatus:output_type -> keepassgo.v1.GetSessionStatusResponse
+ 3, // 42: keepassgo.v1.VaultService.OpenVault:output_type -> keepassgo.v1.OpenVaultResponse
+ 5, // 43: keepassgo.v1.VaultService.OpenRemoteVault:output_type -> keepassgo.v1.OpenRemoteVaultResponse
+ 7, // 44: keepassgo.v1.VaultService.SaveVault:output_type -> keepassgo.v1.SaveVaultResponse
+ 9, // 45: keepassgo.v1.VaultService.LockVault:output_type -> keepassgo.v1.LockVaultResponse
+ 11, // 46: keepassgo.v1.VaultService.UnlockVault:output_type -> keepassgo.v1.UnlockVaultResponse
+ 14, // 47: keepassgo.v1.VaultService.FindBrowserLogins:output_type -> keepassgo.v1.FindBrowserLoginsResponse
+ 16, // 48: keepassgo.v1.VaultService.GetBrowserCredential:output_type -> keepassgo.v1.GetBrowserCredentialResponse
+ 19, // 49: keepassgo.v1.VaultService.ListEntries:output_type -> keepassgo.v1.ListEntriesResponse
+ 21, // 50: keepassgo.v1.VaultService.ListGroups:output_type -> keepassgo.v1.ListGroupsResponse
+ 23, // 51: keepassgo.v1.VaultService.CreateGroup:output_type -> keepassgo.v1.CreateGroupResponse
+ 25, // 52: keepassgo.v1.VaultService.RenameGroup:output_type -> keepassgo.v1.RenameGroupResponse
+ 27, // 53: keepassgo.v1.VaultService.DeleteGroup:output_type -> keepassgo.v1.DeleteGroupResponse
+ 29, // 54: keepassgo.v1.VaultService.UpsertEntry:output_type -> keepassgo.v1.UpsertEntryResponse
+ 31, // 55: keepassgo.v1.VaultService.DeleteEntry:output_type -> keepassgo.v1.DeleteEntryResponse
+ 33, // 56: keepassgo.v1.VaultService.RestoreEntry:output_type -> keepassgo.v1.RestoreEntryResponse
+ 35, // 57: keepassgo.v1.VaultService.ListEntryHistory:output_type -> keepassgo.v1.ListEntryHistoryResponse
+ 37, // 58: keepassgo.v1.VaultService.RestoreEntryHistory:output_type -> keepassgo.v1.RestoreEntryHistoryResponse
+ 39, // 59: keepassgo.v1.VaultService.ListTemplates:output_type -> keepassgo.v1.ListTemplatesResponse
+ 41, // 60: keepassgo.v1.VaultService.UpsertTemplate:output_type -> keepassgo.v1.UpsertTemplateResponse
+ 43, // 61: keepassgo.v1.VaultService.DeleteTemplate:output_type -> keepassgo.v1.DeleteTemplateResponse
+ 45, // 62: keepassgo.v1.VaultService.InstantiateTemplate:output_type -> keepassgo.v1.InstantiateTemplateResponse
+ 47, // 63: keepassgo.v1.VaultService.ListAttachments:output_type -> keepassgo.v1.ListAttachmentsResponse
+ 49, // 64: keepassgo.v1.VaultService.UploadAttachment:output_type -> keepassgo.v1.UploadAttachmentResponse
+ 51, // 65: keepassgo.v1.VaultService.DownloadAttachment:output_type -> keepassgo.v1.DownloadAttachmentResponse
+ 53, // 66: keepassgo.v1.VaultService.DeleteAttachment:output_type -> keepassgo.v1.DeleteAttachmentResponse
+ 55, // 67: keepassgo.v1.VaultService.CopyEntryField:output_type -> keepassgo.v1.CopyEntryFieldResponse
+ 57, // 68: keepassgo.v1.VaultService.GeneratePassword:output_type -> keepassgo.v1.GeneratePasswordResponse
+ 41, // [41:69] is the sub-list for method output_type
+ 13, // [13:41] is the sub-list for method input_type
+ 13, // [13:13] is the sub-list for extension type_name
+ 13, // [13:13] is the sub-list for extension extendee
+ 0, // [0:13] is the sub-list for field type_name
}
func init() { file_proto_keepassgo_v1_keepassgo_proto_init() }
@@ -2750,7 +3073,7 @@ func file_proto_keepassgo_v1_keepassgo_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_keepassgo_v1_keepassgo_proto_rawDesc), len(file_proto_keepassgo_v1_keepassgo_proto_rawDesc)),
NumEnums: 0,
- NumMessages: 54,
+ NumMessages: 59,
NumExtensions: 0,
NumServices: 1,
},
diff --git a/proto/keepassgo/v1/keepassgo.proto b/proto/keepassgo/v1/keepassgo.proto
index ef57ec8..5b3208f 100644
--- a/proto/keepassgo/v1/keepassgo.proto
+++ b/proto/keepassgo/v1/keepassgo.proto
@@ -11,6 +11,8 @@ service VaultService {
rpc SaveVault(SaveVaultRequest) returns (SaveVaultResponse);
rpc LockVault(LockVaultRequest) returns (LockVaultResponse);
rpc UnlockVault(UnlockVaultRequest) returns (UnlockVaultResponse);
+ rpc FindBrowserLogins(FindBrowserLoginsRequest) returns (FindBrowserLoginsResponse);
+ rpc GetBrowserCredential(GetBrowserCredentialRequest) returns (GetBrowserCredentialResponse);
rpc ListEntries(ListEntriesRequest) returns (ListEntriesResponse);
rpc ListGroups(ListGroupsRequest) returns (ListGroupsResponse);
rpc CreateGroup(CreateGroupRequest) returns (CreateGroupResponse);
@@ -75,6 +77,35 @@ message UnlockVaultRequest {
message UnlockVaultResponse {}
+message FindBrowserLoginsRequest {
+ string page_url = 1;
+}
+
+message BrowserLoginMatch {
+ string id = 1;
+ string title = 2;
+ string username = 3;
+ string url = 4;
+ repeated string path = 5;
+ string quality = 6;
+}
+
+message FindBrowserLoginsResponse {
+ repeated BrowserLoginMatch matches = 1;
+}
+
+message GetBrowserCredentialRequest {
+ string id = 1;
+ string page_url = 2;
+}
+
+message GetBrowserCredentialResponse {
+ string id = 1;
+ string username = 2;
+ string password = 3;
+ string url = 4;
+}
+
message ListEntriesRequest {
repeated string path = 1;
string query = 2;
diff --git a/proto/keepassgo/v1/keepassgo_grpc.pb.go b/proto/keepassgo/v1/keepassgo_grpc.pb.go
index 2420a58..0be1429 100644
--- a/proto/keepassgo/v1/keepassgo_grpc.pb.go
+++ b/proto/keepassgo/v1/keepassgo_grpc.pb.go
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
-// - protoc v6.33.1
+// - protoc v7.34.1
// source: proto/keepassgo/v1/keepassgo.proto
package keepassgov1
@@ -19,32 +19,34 @@ import (
const _ = grpc.SupportPackageIsVersion9
const (
- VaultService_GetSessionStatus_FullMethodName = "/keepassgo.v1.VaultService/GetSessionStatus"
- VaultService_OpenVault_FullMethodName = "/keepassgo.v1.VaultService/OpenVault"
- VaultService_OpenRemoteVault_FullMethodName = "/keepassgo.v1.VaultService/OpenRemoteVault"
- VaultService_SaveVault_FullMethodName = "/keepassgo.v1.VaultService/SaveVault"
- VaultService_LockVault_FullMethodName = "/keepassgo.v1.VaultService/LockVault"
- VaultService_UnlockVault_FullMethodName = "/keepassgo.v1.VaultService/UnlockVault"
- VaultService_ListEntries_FullMethodName = "/keepassgo.v1.VaultService/ListEntries"
- VaultService_ListGroups_FullMethodName = "/keepassgo.v1.VaultService/ListGroups"
- VaultService_CreateGroup_FullMethodName = "/keepassgo.v1.VaultService/CreateGroup"
- VaultService_RenameGroup_FullMethodName = "/keepassgo.v1.VaultService/RenameGroup"
- VaultService_DeleteGroup_FullMethodName = "/keepassgo.v1.VaultService/DeleteGroup"
- VaultService_UpsertEntry_FullMethodName = "/keepassgo.v1.VaultService/UpsertEntry"
- VaultService_DeleteEntry_FullMethodName = "/keepassgo.v1.VaultService/DeleteEntry"
- VaultService_RestoreEntry_FullMethodName = "/keepassgo.v1.VaultService/RestoreEntry"
- VaultService_ListEntryHistory_FullMethodName = "/keepassgo.v1.VaultService/ListEntryHistory"
- VaultService_RestoreEntryHistory_FullMethodName = "/keepassgo.v1.VaultService/RestoreEntryHistory"
- VaultService_ListTemplates_FullMethodName = "/keepassgo.v1.VaultService/ListTemplates"
- VaultService_UpsertTemplate_FullMethodName = "/keepassgo.v1.VaultService/UpsertTemplate"
- VaultService_DeleteTemplate_FullMethodName = "/keepassgo.v1.VaultService/DeleteTemplate"
- VaultService_InstantiateTemplate_FullMethodName = "/keepassgo.v1.VaultService/InstantiateTemplate"
- VaultService_ListAttachments_FullMethodName = "/keepassgo.v1.VaultService/ListAttachments"
- VaultService_UploadAttachment_FullMethodName = "/keepassgo.v1.VaultService/UploadAttachment"
- VaultService_DownloadAttachment_FullMethodName = "/keepassgo.v1.VaultService/DownloadAttachment"
- VaultService_DeleteAttachment_FullMethodName = "/keepassgo.v1.VaultService/DeleteAttachment"
- VaultService_CopyEntryField_FullMethodName = "/keepassgo.v1.VaultService/CopyEntryField"
- VaultService_GeneratePassword_FullMethodName = "/keepassgo.v1.VaultService/GeneratePassword"
+ VaultService_GetSessionStatus_FullMethodName = "/keepassgo.v1.VaultService/GetSessionStatus"
+ VaultService_OpenVault_FullMethodName = "/keepassgo.v1.VaultService/OpenVault"
+ VaultService_OpenRemoteVault_FullMethodName = "/keepassgo.v1.VaultService/OpenRemoteVault"
+ VaultService_SaveVault_FullMethodName = "/keepassgo.v1.VaultService/SaveVault"
+ VaultService_LockVault_FullMethodName = "/keepassgo.v1.VaultService/LockVault"
+ VaultService_UnlockVault_FullMethodName = "/keepassgo.v1.VaultService/UnlockVault"
+ VaultService_FindBrowserLogins_FullMethodName = "/keepassgo.v1.VaultService/FindBrowserLogins"
+ VaultService_GetBrowserCredential_FullMethodName = "/keepassgo.v1.VaultService/GetBrowserCredential"
+ VaultService_ListEntries_FullMethodName = "/keepassgo.v1.VaultService/ListEntries"
+ VaultService_ListGroups_FullMethodName = "/keepassgo.v1.VaultService/ListGroups"
+ VaultService_CreateGroup_FullMethodName = "/keepassgo.v1.VaultService/CreateGroup"
+ VaultService_RenameGroup_FullMethodName = "/keepassgo.v1.VaultService/RenameGroup"
+ VaultService_DeleteGroup_FullMethodName = "/keepassgo.v1.VaultService/DeleteGroup"
+ VaultService_UpsertEntry_FullMethodName = "/keepassgo.v1.VaultService/UpsertEntry"
+ VaultService_DeleteEntry_FullMethodName = "/keepassgo.v1.VaultService/DeleteEntry"
+ VaultService_RestoreEntry_FullMethodName = "/keepassgo.v1.VaultService/RestoreEntry"
+ VaultService_ListEntryHistory_FullMethodName = "/keepassgo.v1.VaultService/ListEntryHistory"
+ VaultService_RestoreEntryHistory_FullMethodName = "/keepassgo.v1.VaultService/RestoreEntryHistory"
+ VaultService_ListTemplates_FullMethodName = "/keepassgo.v1.VaultService/ListTemplates"
+ VaultService_UpsertTemplate_FullMethodName = "/keepassgo.v1.VaultService/UpsertTemplate"
+ VaultService_DeleteTemplate_FullMethodName = "/keepassgo.v1.VaultService/DeleteTemplate"
+ VaultService_InstantiateTemplate_FullMethodName = "/keepassgo.v1.VaultService/InstantiateTemplate"
+ VaultService_ListAttachments_FullMethodName = "/keepassgo.v1.VaultService/ListAttachments"
+ VaultService_UploadAttachment_FullMethodName = "/keepassgo.v1.VaultService/UploadAttachment"
+ VaultService_DownloadAttachment_FullMethodName = "/keepassgo.v1.VaultService/DownloadAttachment"
+ VaultService_DeleteAttachment_FullMethodName = "/keepassgo.v1.VaultService/DeleteAttachment"
+ VaultService_CopyEntryField_FullMethodName = "/keepassgo.v1.VaultService/CopyEntryField"
+ VaultService_GeneratePassword_FullMethodName = "/keepassgo.v1.VaultService/GeneratePassword"
)
// VaultServiceClient is the client API for VaultService service.
@@ -57,6 +59,8 @@ type VaultServiceClient interface {
SaveVault(ctx context.Context, in *SaveVaultRequest, opts ...grpc.CallOption) (*SaveVaultResponse, error)
LockVault(ctx context.Context, in *LockVaultRequest, opts ...grpc.CallOption) (*LockVaultResponse, error)
UnlockVault(ctx context.Context, in *UnlockVaultRequest, opts ...grpc.CallOption) (*UnlockVaultResponse, error)
+ FindBrowserLogins(ctx context.Context, in *FindBrowserLoginsRequest, opts ...grpc.CallOption) (*FindBrowserLoginsResponse, error)
+ GetBrowserCredential(ctx context.Context, in *GetBrowserCredentialRequest, opts ...grpc.CallOption) (*GetBrowserCredentialResponse, error)
ListEntries(ctx context.Context, in *ListEntriesRequest, opts ...grpc.CallOption) (*ListEntriesResponse, error)
ListGroups(ctx context.Context, in *ListGroupsRequest, opts ...grpc.CallOption) (*ListGroupsResponse, error)
CreateGroup(ctx context.Context, in *CreateGroupRequest, opts ...grpc.CallOption) (*CreateGroupResponse, error)
@@ -147,6 +151,26 @@ func (c *vaultServiceClient) UnlockVault(ctx context.Context, in *UnlockVaultReq
return out, nil
}
+func (c *vaultServiceClient) FindBrowserLogins(ctx context.Context, in *FindBrowserLoginsRequest, opts ...grpc.CallOption) (*FindBrowserLoginsResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(FindBrowserLoginsResponse)
+ err := c.cc.Invoke(ctx, VaultService_FindBrowserLogins_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *vaultServiceClient) GetBrowserCredential(ctx context.Context, in *GetBrowserCredentialRequest, opts ...grpc.CallOption) (*GetBrowserCredentialResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(GetBrowserCredentialResponse)
+ err := c.cc.Invoke(ctx, VaultService_GetBrowserCredential_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
func (c *vaultServiceClient) ListEntries(ctx context.Context, in *ListEntriesRequest, opts ...grpc.CallOption) (*ListEntriesResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListEntriesResponse)
@@ -357,6 +381,8 @@ type VaultServiceServer interface {
SaveVault(context.Context, *SaveVaultRequest) (*SaveVaultResponse, error)
LockVault(context.Context, *LockVaultRequest) (*LockVaultResponse, error)
UnlockVault(context.Context, *UnlockVaultRequest) (*UnlockVaultResponse, error)
+ FindBrowserLogins(context.Context, *FindBrowserLoginsRequest) (*FindBrowserLoginsResponse, error)
+ GetBrowserCredential(context.Context, *GetBrowserCredentialRequest) (*GetBrowserCredentialResponse, error)
ListEntries(context.Context, *ListEntriesRequest) (*ListEntriesResponse, error)
ListGroups(context.Context, *ListGroupsRequest) (*ListGroupsResponse, error)
CreateGroup(context.Context, *CreateGroupRequest) (*CreateGroupResponse, error)
@@ -405,6 +431,12 @@ func (UnimplementedVaultServiceServer) LockVault(context.Context, *LockVaultRequ
func (UnimplementedVaultServiceServer) UnlockVault(context.Context, *UnlockVaultRequest) (*UnlockVaultResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UnlockVault not implemented")
}
+func (UnimplementedVaultServiceServer) FindBrowserLogins(context.Context, *FindBrowserLoginsRequest) (*FindBrowserLoginsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method FindBrowserLogins not implemented")
+}
+func (UnimplementedVaultServiceServer) GetBrowserCredential(context.Context, *GetBrowserCredentialRequest) (*GetBrowserCredentialResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method GetBrowserCredential not implemented")
+}
func (UnimplementedVaultServiceServer) ListEntries(context.Context, *ListEntriesRequest) (*ListEntriesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListEntries not implemented")
}
@@ -594,6 +626,42 @@ func _VaultService_UnlockVault_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
+func _VaultService_FindBrowserLogins_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(FindBrowserLoginsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(VaultServiceServer).FindBrowserLogins(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: VaultService_FindBrowserLogins_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(VaultServiceServer).FindBrowserLogins(ctx, req.(*FindBrowserLoginsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _VaultService_GetBrowserCredential_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(GetBrowserCredentialRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(VaultServiceServer).GetBrowserCredential(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: VaultService_GetBrowserCredential_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(VaultServiceServer).GetBrowserCredential(ctx, req.(*GetBrowserCredentialRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
func _VaultService_ListEntries_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListEntriesRequest)
if err := dec(in); err != nil {
@@ -985,6 +1053,14 @@ var VaultService_ServiceDesc = grpc.ServiceDesc{
MethodName: "UnlockVault",
Handler: _VaultService_UnlockVault_Handler,
},
+ {
+ MethodName: "FindBrowserLogins",
+ Handler: _VaultService_FindBrowserLogins_Handler,
+ },
+ {
+ MethodName: "GetBrowserCredential",
+ Handler: _VaultService_GetBrowserCredential_Handler,
+ },
{
MethodName: "ListEntries",
Handler: _VaultService_ListEntries_Handler,