generator share links; secure send copy message
This commit is contained in:
@@ -94,8 +94,30 @@
|
||||
</p>
|
||||
<div class="link-row">
|
||||
<input ref="linkInput" class="form-control mono" :value="link" readonly @focus="selectAll" />
|
||||
<button class="btn btn-primary" @click="copyLink">{{ copied ? 'Copied' : 'Copy' }}</button>
|
||||
<button class="btn btn-primary" @click="copyLink">{{ copied ? 'Copied' : 'Copy link' }}</button>
|
||||
<!--
|
||||
Copies a whole sentence, not the bare URL. Pasted into an EMPTY chat
|
||||
box there is nothing selected for the link to attach itself to - which
|
||||
is the failure this button exists to prevent. See copyMessage().
|
||||
-->
|
||||
<button class="btn btn-secondary" @click="copyMessage">
|
||||
{{ messagecopied ? 'Copied' : 'Copy message' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
The warning that matters, stated where the mistake gets made. The hint
|
||||
below is about the key being unrecoverable, which is a different point
|
||||
and does not stop anybody pasting the password itself.
|
||||
-->
|
||||
<div class="alert-send">
|
||||
<strong>Send the link, not the secret.</strong>
|
||||
If the password is already typed in a chat box, delete it before pasting
|
||||
this. Pasting a link over selected text turns that text into the link's
|
||||
caption, and the secret then travels in the message itself - the link
|
||||
beside it protects nothing.
|
||||
</div>
|
||||
|
||||
<p class="control-hint">
|
||||
This is the only time the link is shown - it is not stored anywhere you can
|
||||
look it up, and the key in it exists nowhere else.
|
||||
@@ -142,6 +164,7 @@ const busy = ref(false)
|
||||
const error = ref('')
|
||||
const link = ref('')
|
||||
const copied = ref(false)
|
||||
const messagecopied = ref(false)
|
||||
const linkInput = ref(null)
|
||||
|
||||
// Only nag once there is something to nag about: an empty box is not a mistake.
|
||||
@@ -222,6 +245,35 @@ async function copyLink() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The link with a sentence around it.
|
||||
*
|
||||
* A bare URL invites being pasted onto text that is already in the chat box,
|
||||
* and a chat client turns the selection into the link's caption - so the secret
|
||||
* travels as the visible message and the link protects nothing. It has happened
|
||||
* in production: six LAPS passwords sent as the caption of a link whose whole
|
||||
* job was to keep them out of the chat.
|
||||
*
|
||||
* A sentence has nowhere to attach itself. Pasted into an empty box it is a
|
||||
* message; pasted over a selection it replaces it rather than decorating it.
|
||||
* Plain text on purpose - a rich-text flavour is what would let a secret ride
|
||||
* along as markup.
|
||||
*/
|
||||
async function copyMessage() {
|
||||
const opens = views.value === 1
|
||||
? 'It opens once and then destroys itself'
|
||||
: `It opens ${views.value} times and then destroys itself`
|
||||
const message =
|
||||
`Secure link - ${opens}, and expires ${expiryLabel.value}: ${link.value}`
|
||||
try {
|
||||
await navigator.clipboard.writeText(message)
|
||||
messagecopied.value = true
|
||||
setTimeout(() => { messagecopied.value = false }, 2000)
|
||||
} catch (err) {
|
||||
selectAll()
|
||||
}
|
||||
}
|
||||
|
||||
function selectAll() {
|
||||
linkInput.value?.select()
|
||||
}
|
||||
@@ -245,6 +297,17 @@ function reset() {
|
||||
.counter.over { color: var(--warning); font-weight: 600; }
|
||||
.control-note { color: var(--warning); font-size: 0.875rem; margin: 8px 0; }
|
||||
.control-hint { color: var(--text-light); font-size: 0.8125rem; margin: 8px 0 12px; }
|
||||
/* Loud enough to be read before the paste, quiet enough not to look like an
|
||||
error on a page where nothing went wrong. */
|
||||
.alert-send {
|
||||
border-left: 3px solid var(--warning);
|
||||
background: var(--bg-card-solid);
|
||||
padding: 0.6rem 0.9rem;
|
||||
margin: 0.75rem 0;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.alert-send strong { display: block; margin-bottom: 2px; }
|
||||
.link-row { display: flex; gap: 8px; align-items: center; margin: 0.5rem 0; }
|
||||
.link-row .form-control { flex: 1; }
|
||||
.mono { font-family: 'SF Mono', 'Monaco', 'Consolas', monospace; font-size: 0.875rem; }
|
||||
|
||||
Reference in New Issue
Block a user