show approval errors in approval view
This commit is contained in:
parent
a75f34865e
commit
760987f09b
@ -10,6 +10,7 @@ export let appState = writable({
|
|||||||
credentialStatus: 'locked',
|
credentialStatus: 'locked',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
export async function acceptRequest() {
|
export async function acceptRequest() {
|
||||||
let req = await get(appState).pendingRequests.get();
|
let req = await get(appState).pendingRequests.get();
|
||||||
appState.update($appState => {
|
appState.update($appState => {
|
||||||
@ -20,6 +21,7 @@ export async function acceptRequest() {
|
|||||||
navigate('Approve');
|
navigate('Approve');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function completeRequest() {
|
export function completeRequest() {
|
||||||
appState.update($appState => {
|
appState.update($appState => {
|
||||||
$appState.currentRequest = null;
|
$appState.currentRequest = null;
|
||||||
|
@ -1,17 +1,35 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { onMount } from 'svelte';
|
||||||
import { invoke } from '@tauri-apps/api/tauri';
|
import { invoke } from '@tauri-apps/api/tauri';
|
||||||
|
|
||||||
import { navigate } from '../lib/routing.js';
|
import { navigate } from '../lib/routing.js';
|
||||||
import { appState } from '../lib/state.js';
|
import { appState, completeRequest } from '../lib/state.js';
|
||||||
|
import ErrorAlert from '../ui/ErrorAlert.svelte';
|
||||||
import Link from '../ui/Link.svelte';
|
import Link from '../ui/Link.svelte';
|
||||||
import Icon from '../ui/Icon.svelte';
|
|
||||||
|
|
||||||
|
|
||||||
|
// Send response to backend, display error if applicable
|
||||||
|
let error, alert;
|
||||||
|
async function respond() {
|
||||||
|
let {id, approval} = $appState.currentRequest;
|
||||||
|
try {
|
||||||
|
await invoke('respond', {response: {id, approval}});
|
||||||
|
navigate('ShowResponse');
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (error) {
|
||||||
|
alert.shake();
|
||||||
|
}
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Approval has one of several outcomes depending on current credential state
|
||||||
async function approve() {
|
async function approve() {
|
||||||
$appState.currentRequest.approval = 'Approved';
|
$appState.currentRequest.approval = 'Approved';
|
||||||
let status = await invoke('get_session_status');
|
let status = await invoke('get_session_status');
|
||||||
if (status === 'unlocked') {
|
if (status === 'unlocked') {
|
||||||
navigate('ShowResponse');
|
await respond();
|
||||||
}
|
}
|
||||||
else if (status === 'locked') {
|
else if (status === 'locked') {
|
||||||
navigate('Unlock');
|
navigate('Unlock');
|
||||||
@ -21,40 +39,69 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deny() {
|
// Denial has only one
|
||||||
|
async function deny() {
|
||||||
$appState.currentRequest.approval = 'Denied';
|
$appState.currentRequest.approval = 'Denied';
|
||||||
navigate('ShowResponse');
|
await respond();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract executable name from full path
|
||||||
let appName = null;
|
let appName = null;
|
||||||
if ($appState.currentRequest.clients.length === 1) {
|
if ($appState.currentRequest.clients.length === 1) {
|
||||||
let path = $appState.currentRequest.clients[0].exe;
|
let path = $appState.currentRequest.clients[0].exe;
|
||||||
// grab the filename from the path
|
|
||||||
let m = path.match(/\/([^/]+?$)|\\([^\\]+?$)/);
|
let m = path.match(/\/([^/]+?$)|\\([^\\]+?$)/);
|
||||||
appName = m[1] || m[2];
|
appName = m[1] || m[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Executable paths can be long, so ensure they only break on \ or /
|
||||||
|
function breakPath(client) {
|
||||||
|
return client.exe.replace(/(\\|\/)/g, '$1<wbr>');
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the request has already been approved/denied, send response immediately
|
||||||
|
onMount(async () => {
|
||||||
|
if ($appState.currentRequest.approval) {
|
||||||
|
await respond();
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<div class="flex flex-col space-y-4 p-4 m-auto max-w-max h-screen justify-center">
|
<!-- Don't render at all if we're just going to immediately proceed to the next screen -->
|
||||||
<!-- <div class="p-4 rounded-box border-2 border-neutral-content"> -->
|
{#if !$appState.currentRequest.approval}
|
||||||
|
<div class="flex flex-col space-y-4 p-4 m-auto max-w-xl h-screen items-center justify-center">
|
||||||
|
{#if error}
|
||||||
|
<ErrorAlert bind:this={alert}>
|
||||||
|
{error}
|
||||||
|
<svelte:fragment slot="buttons">
|
||||||
|
<button class="btn btn-sm btn-alert-error" on:click={completeRequest}>Cancel</button>
|
||||||
|
<button class="btn btn-sm btn-alert-error" on:click={respond}>Retry</button>
|
||||||
|
</svelte:fragment>
|
||||||
|
</ErrorAlert>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div class="space-y-1 mb-4">
|
<div class="space-y-1 mb-4">
|
||||||
<h2 class="text-xl font-bold">{appName ? `"${appName}"` : 'An appplication'} would like to access your AWS credentials.</h2>
|
<h2 class="text-xl font-bold">{appName ? `"${appName}"` : 'An appplication'} would like to access your AWS credentials.</h2>
|
||||||
{#each $appState.currentRequest.clients as client}
|
|
||||||
<p>Path: {client ? client.exe : 'Unknown'}</p>
|
<div class="grid grid-cols-[auto_1fr] gap-x-3">
|
||||||
<p>PID: {client ? client.pid : 'Unknown'}</p>
|
{#each $appState.currentRequest.clients as client}
|
||||||
{/each}
|
<div class="text-right">Path:</div>
|
||||||
|
<code class="">{@html client ? breakPath(client) : 'Unknown'}</code>
|
||||||
|
<div class="text-right">PID:</div>
|
||||||
|
<code>{client ? client.pid : 'Unknown'}</code>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-2">
|
<div class="w-full flex justify-between">
|
||||||
<Link target="{deny}" hotkey="Escape">
|
<Link target={deny} hotkey="Escape">
|
||||||
<button class="btn btn-error justify-self-start">
|
<button class="btn btn-error justify-self-start">
|
||||||
Deny
|
Deny
|
||||||
<kbd class="ml-2 normal-case px-1 py-0.5 rounded border border-neutral">Esc</kbd>
|
<kbd class="ml-2 normal-case px-1 py-0.5 rounded border border-neutral">Esc</kbd>
|
||||||
</button>
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link target="{approve}" hotkey="Enter" shift="{true}">
|
<Link target={approve} hotkey="Enter" shift="{true}">
|
||||||
<button class="btn btn-success justify-self-end">
|
<button class="btn btn-success justify-self-end">
|
||||||
Approve
|
Approve
|
||||||
<kbd class="ml-2 normal-case px-1 py-0.5 rounded border border-neutral">Shift</kbd>
|
<kbd class="ml-2 normal-case px-1 py-0.5 rounded border border-neutral">Shift</kbd>
|
||||||
@ -63,4 +110,5 @@
|
|||||||
</button>
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
@ -29,7 +29,7 @@
|
|||||||
try {
|
try {
|
||||||
await invoke('save_credentials', {credentials, passphrase});
|
await invoke('save_credentials', {credentials, passphrase});
|
||||||
if ($appState.currentRequest) {
|
if ($appState.currentRequest) {
|
||||||
navigate('ShowResponse');
|
navigate('Approve');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
navigate('Home');
|
navigate('Home');
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { draw, fade } from 'svelte/transition';
|
import { draw, fade } from 'svelte/transition';
|
||||||
import { invoke } from '@tauri-apps/api/tauri';
|
|
||||||
|
|
||||||
import { appState, completeRequest } from '../lib/state.js';
|
import { appState, completeRequest } from '../lib/state.js';
|
||||||
import ErrorAlert from '../ui/ErrorAlert.svelte';
|
|
||||||
import Link from '../ui/Link.svelte';
|
|
||||||
|
|
||||||
let success = false;
|
let success = false;
|
||||||
let error = null;
|
let error = null;
|
||||||
@ -14,55 +11,28 @@
|
|||||||
let fadeDuration = drawDuration * 0.6;
|
let fadeDuration = drawDuration * 0.6;
|
||||||
let fadeDelay = drawDuration * 0.4;
|
let fadeDelay = drawDuration * 0.4;
|
||||||
|
|
||||||
async function respond() {
|
onMount(() => {
|
||||||
let packet = {
|
window.setTimeout(
|
||||||
id: $appState.currentRequest.id,
|
completeRequest,
|
||||||
approval: $appState.currentRequest.approval,
|
// Extra 50ms so the window can finish disappearing before the redraw
|
||||||
};
|
Math.min(5000, $appState.config.rehide_ms + 50),
|
||||||
|
)
|
||||||
try {
|
})
|
||||||
await invoke('respond', {response: packet});
|
|
||||||
success = true;
|
|
||||||
window.setTimeout(
|
|
||||||
completeRequest,
|
|
||||||
// Extra 50ms so the window can finish disappearing before the redraw
|
|
||||||
Math.min(5000, $appState.config.rehide_ms + 50),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
error = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
onMount(respond);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
{#if error}
|
<div class="flex flex-col h-screen items-center justify-center max-w-max m-auto">
|
||||||
<div class="flex flex-col h-screen items-center justify-center m-auto max-w-lg">
|
{#if $appState.currentRequest.approval === 'Approved'}
|
||||||
<ErrorAlert>
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-36 h-36" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor">
|
||||||
{error}
|
<path in:draw="{{duration: drawDuration}}" stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
<svelte:fragment slot="buttons">
|
</svg>
|
||||||
<Link target="Home">
|
{:else}
|
||||||
<button class="btn btn-sm btn-alert-error" on:click={() => navigate('Home')}>Ok</button>
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-36 h-36" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor">
|
||||||
</Link>
|
<path in:draw="{{duration: 500}}" stroke-linecap="round" stroke-linejoin="round" d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
</svelte:fragment>
|
</svg>
|
||||||
</ErrorAlert>
|
{/if}
|
||||||
</div>
|
|
||||||
{:else if success}
|
|
||||||
<div class="flex flex-col h-screen items-center justify-center max-w-max m-auto">
|
|
||||||
{#if $appState.currentRequest.approval === 'Approved'}
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-36 h-36" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor">
|
|
||||||
<path in:draw="{{duration: drawDuration}}" stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
||||||
</svg>
|
|
||||||
{:else}
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-36 h-36" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor">
|
|
||||||
<path in:draw="{{duration: 500}}" stroke-linecap="round" stroke-linejoin="round" d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
||||||
</svg>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div in:fade="{{duration: fadeDuration, delay: fadeDelay}}" class="text-2xl font-bold">
|
<div in:fade="{{duration: fadeDuration, delay: fadeDelay}}" class="text-2xl font-bold">
|
||||||
{$appState.currentRequest.approval}!
|
{$appState.currentRequest.approval}!
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
</div>
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
let r = await invoke('unlock', {passphrase});
|
let r = await invoke('unlock', {passphrase});
|
||||||
$appState.credentialStatus = 'unlocked';
|
$appState.credentialStatus = 'unlocked';
|
||||||
if ($appState.currentRequest) {
|
if ($appState.currentRequest) {
|
||||||
navigate('ShowResponse');
|
navigate('Approve');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
navigate('Home');
|
navigate('Home');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user