mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-23 09:08:32 +02:00
Merge branch 'main' into omnara/slit-unveiling
This commit is contained in:
@@ -12,14 +12,16 @@ interface CacheEntry<T> {
|
|||||||
expiresAt: number;
|
expiresAt: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Result<T> = { error: unknown } | T;
|
||||||
|
|
||||||
const CACHE_TTL_MS = 60 * 1000; // 1 minute cache TTL
|
const CACHE_TTL_MS = 60 * 1000; // 1 minute cache TTL
|
||||||
const _cache: Record<string, CacheEntry<unknown>> = {};
|
const _cache: Record<string, CacheEntry<unknown>> = {};
|
||||||
|
|
||||||
async function op(
|
async function op(
|
||||||
args: CallTemplateFunctionArgs,
|
args: CallTemplateFunctionArgs,
|
||||||
): Promise<{ client?: Client; clientHash?: string; error?: unknown }> {
|
): Promise<Result<{ client: Client; clientHash: string }>> {
|
||||||
let authMethod: string | DesktopAuth | null = null;
|
let authMethod: string | DesktopAuth;
|
||||||
let hash: string | null = null;
|
let hash: string;
|
||||||
switch (args.values.authMethod) {
|
switch (args.values.authMethod) {
|
||||||
case 'desktop': {
|
case 'desktop': {
|
||||||
const account = args.values.token;
|
const account = args.values.token;
|
||||||
@@ -37,18 +39,20 @@ async function op(
|
|||||||
authMethod = token;
|
authMethod = token;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
return { error: 'Invalid authentication method' };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hash == null || authMethod == null) return { error: 'Invalid authentication method' };
|
if (!_clients[hash]) {
|
||||||
|
try {
|
||||||
try {
|
_clients[hash] = await createClient({
|
||||||
_clients[hash] ??= await createClient({
|
auth: authMethod,
|
||||||
auth: authMethod,
|
integrationName: 'Yaak 1Password Plugin',
|
||||||
integrationName: 'Yaak 1Password Plugin',
|
integrationVersion: 'v1.0.0',
|
||||||
integrationVersion: 'v1.0.0',
|
});
|
||||||
});
|
} catch (e) {
|
||||||
} catch (e) {
|
return { error: e };
|
||||||
return { error: e };
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { client: _clients[hash], clientHash: hash };
|
return { client: _clients[hash], clientHash: hash };
|
||||||
@@ -59,47 +63,35 @@ async function getValue(
|
|||||||
vaultId?: JsonPrimitive,
|
vaultId?: JsonPrimitive,
|
||||||
itemId?: JsonPrimitive,
|
itemId?: JsonPrimitive,
|
||||||
fieldId?: JsonPrimitive,
|
fieldId?: JsonPrimitive,
|
||||||
): Promise<{ value?: string; error?: unknown }> {
|
): Promise<Result<{ value: string }>> {
|
||||||
const { client, error, clientHash } = await op(args);
|
const res = await op(args);
|
||||||
if (!client || !clientHash) return { error };
|
if ('error' in res) return { error: res.error };
|
||||||
|
const clientHash = res.clientHash;
|
||||||
|
const client = res.client;
|
||||||
|
|
||||||
if (vaultId && typeof vaultId === 'string') {
|
if (!vaultId || typeof vaultId !== 'string') {
|
||||||
const vaultCacheKey = `${clientHash}:vault:${vaultId}`;
|
|
||||||
const cachedVault = getCached(vaultCacheKey);
|
|
||||||
if (!cachedVault) {
|
|
||||||
try {
|
|
||||||
const vault = await client.vaults.getOverview(vaultId);
|
|
||||||
setCache(vaultCacheKey, vault);
|
|
||||||
} catch {
|
|
||||||
return { error: `Vault ${vaultId} not found` };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return { error: 'No vault specified' };
|
return { error: 'No vault specified' };
|
||||||
}
|
}
|
||||||
|
if (!itemId || typeof itemId !== 'string') {
|
||||||
if (itemId && typeof itemId === 'string') {
|
|
||||||
const itemCacheKey = `${clientHash}:item:${vaultId}:${itemId}`;
|
|
||||||
try {
|
|
||||||
const item =
|
|
||||||
getCached<Awaited<ReturnType<typeof client.items.get>>>(itemCacheKey) ??
|
|
||||||
setCache(itemCacheKey, await client.items.get(vaultId, itemId));
|
|
||||||
if (fieldId && typeof fieldId === 'string') {
|
|
||||||
const field = item.fields.find((f) => f.id === fieldId);
|
|
||||||
if (field) {
|
|
||||||
return { value: field.value };
|
|
||||||
} else {
|
|
||||||
return { error: `Field ${fieldId} not found in item ${itemId} in vault ${vaultId}` };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
return { error: `Item ${itemId} not found in vault ${vaultId}` };
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return { error: 'No item specified' };
|
return { error: 'No item specified' };
|
||||||
}
|
}
|
||||||
|
if (!fieldId || typeof fieldId !== 'string') {
|
||||||
|
return { error: 'No field specified' };
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
try {
|
||||||
|
const cacheKey = `${clientHash}:item:${vaultId}:${itemId}:${fieldId}`;
|
||||||
|
let value = getCached<string>(cacheKey);
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
value = await client.secrets.resolve(`op://${vaultId}/${itemId}/${fieldId}`);
|
||||||
|
setCache(cacheKey, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { value };
|
||||||
|
} catch (e) {
|
||||||
|
return { error: e };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const plugin: PluginDefinition = {
|
export const plugin: PluginDefinition = {
|
||||||
@@ -161,8 +153,10 @@ export const plugin: PluginDefinition = {
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
options: [],
|
options: [],
|
||||||
async dynamic(_ctx, args) {
|
async dynamic(_ctx, args) {
|
||||||
const { client, clientHash } = await op(args);
|
const res = await op(args);
|
||||||
if (client == null || clientHash == null) return { hidden: true };
|
if ('error' in res) return { hidden: true };
|
||||||
|
const clientHash = res.clientHash;
|
||||||
|
const client = res.client;
|
||||||
|
|
||||||
const cacheKey = `${clientHash}:vaults`;
|
const cacheKey = `${clientHash}:vaults`;
|
||||||
const cachedVaults =
|
const cachedVaults =
|
||||||
@@ -170,11 +164,22 @@ export const plugin: PluginDefinition = {
|
|||||||
const vaults =
|
const vaults =
|
||||||
cachedVaults ??
|
cachedVaults ??
|
||||||
setCache(cacheKey, await client.vaults.list({ decryptDetails: true }));
|
setCache(cacheKey, await client.vaults.list({ decryptDetails: true }));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
options: vaults.map((vault) => ({
|
options: vaults.map((vault) => {
|
||||||
label: `${vault.title} (${vault.activeItemCount} Items)`,
|
let title = vault.id;
|
||||||
value: vault.id,
|
if ('title' in vault) {
|
||||||
})),
|
title = vault.title;
|
||||||
|
} else if ('name' in vault) {
|
||||||
|
// The SDK returns 'name' instead of 'title' but the bindings still use 'title'
|
||||||
|
title = (vault as { name: string }).name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
label: `${title} (${vault.activeItemCount} Items)`,
|
||||||
|
value: vault.id,
|
||||||
|
};
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -184,8 +189,11 @@ export const plugin: PluginDefinition = {
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
options: [],
|
options: [],
|
||||||
async dynamic(_ctx, args) {
|
async dynamic(_ctx, args) {
|
||||||
const { client, clientHash } = await op(args);
|
const res = await op(args);
|
||||||
if (client == null || clientHash == null) return { hidden: true };
|
if ('error' in res) return { hidden: true };
|
||||||
|
const clientHash = res.clientHash;
|
||||||
|
const client = res.client;
|
||||||
|
|
||||||
const vaultId = args.values.vault;
|
const vaultId = args.values.vault;
|
||||||
if (typeof vaultId !== 'string') return { hidden: true };
|
if (typeof vaultId !== 'string') return { hidden: true };
|
||||||
|
|
||||||
@@ -212,8 +220,11 @@ export const plugin: PluginDefinition = {
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
options: [],
|
options: [],
|
||||||
async dynamic(_ctx, args) {
|
async dynamic(_ctx, args) {
|
||||||
const { client, clientHash } = await op(args);
|
const res = await op(args);
|
||||||
if (client == null || clientHash == null) return { hidden: true };
|
if ('error' in res) return { hidden: true };
|
||||||
|
const clientHash = res.clientHash;
|
||||||
|
const client = res.client;
|
||||||
|
|
||||||
const vaultId = args.values.vault;
|
const vaultId = args.values.vault;
|
||||||
const itemId = args.values.item;
|
const itemId = args.values.item;
|
||||||
if (typeof vaultId !== 'string' || typeof itemId !== 'string') {
|
if (typeof vaultId !== 'string' || typeof itemId !== 'string') {
|
||||||
@@ -239,12 +250,12 @@ export const plugin: PluginDefinition = {
|
|||||||
const vaultId = args.values.vault;
|
const vaultId = args.values.vault;
|
||||||
const itemId = args.values.item;
|
const itemId = args.values.item;
|
||||||
const fieldId = args.values.field;
|
const fieldId = args.values.field;
|
||||||
const { value, error } = await getValue(args, vaultId, itemId, fieldId);
|
const res = await getValue(args, vaultId, itemId, fieldId);
|
||||||
if (error) {
|
if ('error' in res) {
|
||||||
throw error;
|
throw res.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value ?? '';
|
return res.value;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user