Tech Tools reachable without a login
This commit is contained in:
@@ -15,22 +15,28 @@ export default [
|
|||||||
path: 'tools',
|
path: 'tools',
|
||||||
name: 'tools',
|
name: 'tools',
|
||||||
component: () => import('./views/ToolsIndex.vue'),
|
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',
|
path: 'tools/codes',
|
||||||
name: 'tools-codes',
|
name: 'tools-codes',
|
||||||
component: () => import('./views/CodeGenerator.vue'),
|
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',
|
path: 'tools/secure-send',
|
||||||
name: 'tools-secure-send',
|
name: 'tools-secure-send',
|
||||||
component: () => import('./views/SecureSendCreate.vue'),
|
component: () => import('./views/SecureSendCreate.vue'),
|
||||||
// Creating a secret needs a login AND tools.secrets. The route guard covers
|
// Reachable by anyone; the SERVER decides who may actually create. A signed
|
||||||
// the login; the server enforces the permission, and the page surfaces its
|
// in user needs tools.secrets, and a guest needs the site to have turned on
|
||||||
// refusal rather than pretending the form worked.
|
// securesend_allow_guests. The page reads that setting so a guest who
|
||||||
meta: { requiresAuth: true, plugin: 'tools' }
|
// cannot create is told so, instead of being handed a form that 401s.
|
||||||
|
meta: { plugin: 'tools' }
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -17,13 +17,25 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</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">
|
<div v-if="!supported" class="card control-note">
|
||||||
This browser cannot encrypt in page (Web Crypto is unavailable, which
|
This browser cannot encrypt in page (Web Crypto is unavailable, which
|
||||||
usually means the site is not being served over HTTPS). Secure send needs
|
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.
|
it, because the whole point is that the server never sees your text.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-else-if="!link">
|
<template v-else-if="mayCreate && !link">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<label class="field">
|
<label class="field">
|
||||||
<span class="field-label">Secret</span>
|
<span class="field-label">Secret</span>
|
||||||
@@ -94,15 +106,29 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { toolsApi } from '../api'
|
import { toolsApi } from '../api'
|
||||||
import { withBase } from '@/utils/basePath'
|
import { withBase } from '@/utils/basePath'
|
||||||
import { getSiteBaseUrl } from '@/utils/siteSettings'
|
import { getSiteBaseUrl, getSetting } from '@/utils/siteSettings'
|
||||||
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import {
|
import {
|
||||||
sealSecret, refuseReason, pasteCarriesFiles, cryptoAvailable, MAX_PLAINTEXT,
|
sealSecret, refuseReason, pasteCarriesFiles, cryptoAvailable, MAX_PLAINTEXT,
|
||||||
} from '../securesend'
|
} from '../securesend'
|
||||||
|
|
||||||
const supported = cryptoAvailable()
|
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
|
// 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
|
// "how many people need this password" is the sender's business - a shift
|
||||||
|
|||||||
Reference in New Issue
Block a user