Stop making people sign in to reach tools that need no account
/tools, /tools/codes and /tools/secure-send were all behind requiresAuth. None of them needed to be, and one of them actively contradicted a setting added an hour earlier: securesend_allow_guests lets somebody with no account create a link, and the page they would create it on was behind a login wall. The label generator runs entirely in the browser - no API, no data, nothing to protect - so gating it only ever cost a guest the use of it. THE SERVER STILL DECIDES who may create a secret. A signed-in user needs tools.secrets; a guest needs the site to have opened guest creation. Making the page reachable is not the same as making the action allowed, and the two were conflated. The page now reads the setting on load, so a guest at a site that has NOT opened guest creation is told to sign in instead of being handed a form that was always going to be refused - with a line saying that receiving a link never needs an account, because somebody who lands there confused usually has a link they should be opening instead. A signed-in user always sees the form, even without the permission: the server's "you do not have permission" is a different answer from "sign in", and collapsing them would send somebody to a login page they are already past.
This commit is contained in:
@@ -15,22 +15,28 @@ export default [
|
||||
path: 'tools',
|
||||
name: 'tools',
|
||||
component: () => import('./views/ToolsIndex.vue'),
|
||||
meta: { requiresAuth: true, plugin: 'tools' }
|
||||
// NO requiresAuth. Every tool here is usable without an account: the label
|
||||
// generator runs entirely in the browser, and secure send decides for
|
||||
// itself (a site can let guests create, and receiving never needs a login).
|
||||
// Gating the index turned a public tool into one nobody could reach.
|
||||
meta: { plugin: 'tools' }
|
||||
},
|
||||
{
|
||||
path: 'tools/codes',
|
||||
name: 'tools-codes',
|
||||
component: () => import('./views/CodeGenerator.vue'),
|
||||
meta: { requiresAuth: true, plugin: 'tools' }
|
||||
// Browser-only: no API, no data, nothing to protect.
|
||||
meta: { plugin: 'tools' }
|
||||
},
|
||||
{
|
||||
path: 'tools/secure-send',
|
||||
name: 'tools-secure-send',
|
||||
component: () => import('./views/SecureSendCreate.vue'),
|
||||
// Creating a secret needs a login AND tools.secrets. The route guard covers
|
||||
// the login; the server enforces the permission, and the page surfaces its
|
||||
// refusal rather than pretending the form worked.
|
||||
meta: { requiresAuth: true, plugin: 'tools' }
|
||||
// Reachable by anyone; the SERVER decides who may actually create. A signed
|
||||
// in user needs tools.secrets, and a guest needs the site to have turned on
|
||||
// securesend_allow_guests. The page reads that setting so a guest who
|
||||
// cannot create is told so, instead of being handed a form that 401s.
|
||||
meta: { plugin: 'tools' }
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -17,13 +17,25 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- A guest at a site that has not opened guest creation. Told here rather
|
||||
than after typing a password into a form that was always going to be
|
||||
refused. -->
|
||||
<div v-if="supported && !mayCreate" class="card">
|
||||
<p>Signing in is needed to create a secret link at this site.</p>
|
||||
<p class="muted">
|
||||
Receiving one never needs an account - if somebody sent you a link, open
|
||||
that instead.
|
||||
</p>
|
||||
<router-link to="/login" class="btn btn-primary">Sign in</router-link>
|
||||
</div>
|
||||
|
||||
<div v-if="!supported" class="card control-note">
|
||||
This browser cannot encrypt in page (Web Crypto is unavailable, which
|
||||
usually means the site is not being served over HTTPS). Secure send needs
|
||||
it, because the whole point is that the server never sees your text.
|
||||
</div>
|
||||
|
||||
<template v-else-if="!link">
|
||||
<template v-else-if="mayCreate && !link">
|
||||
<div class="card">
|
||||
<label class="field">
|
||||
<span class="field-label">Secret</span>
|
||||
@@ -94,15 +106,29 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { toolsApi } from '../api'
|
||||
import { withBase } from '@/utils/basePath'
|
||||
import { getSiteBaseUrl } from '@/utils/siteSettings'
|
||||
import { getSiteBaseUrl, getSetting } from '@/utils/siteSettings'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import {
|
||||
sealSecret, refuseReason, pasteCarriesFiles, cryptoAvailable, MAX_PLAINTEXT,
|
||||
} from '../securesend'
|
||||
|
||||
const supported = cryptoAvailable()
|
||||
const auth = useAuthStore()
|
||||
|
||||
// Whether THIS visitor can create one. A signed-in user always sees the form -
|
||||
// the server still enforces tools.secrets and says so if they lack it, which is
|
||||
// a different message from "sign in". A guest sees it only where the site has
|
||||
// opened guest creation.
|
||||
const mayCreate = ref(true)
|
||||
|
||||
onMounted(async () => {
|
||||
if (auth.isAuthenticated) return
|
||||
const allowed = await getSetting('securesend_allow_guests', 'false')
|
||||
mayCreate.value = String(allowed).toLowerCase() === 'true'
|
||||
})
|
||||
|
||||
// Matches the server's ceiling. A free number rather than a dropdown because
|
||||
// "how many people need this password" is the sender's business - a shift
|
||||
|
||||
Reference in New Issue
Block a user