Call vanity vanity again
This commit is contained in:
@@ -722,7 +722,7 @@ func TestLoginStoresTheToken(t *testing.T) {
|
|||||||
t.Error("'stay logged in' did not persist the cookie")
|
t.Error("'stay logged in' did not persist the cookie")
|
||||||
}
|
}
|
||||||
|
|
||||||
// The session alone is now enough to claim a custom name.
|
// The session alone is now enough to claim a vanity name.
|
||||||
req, _ := http.NewRequest("POST", h.ts.URL+"/upload", strings.NewReader("two"))
|
req, _ := http.NewRequest("POST", h.ts.URL+"/upload", strings.NewReader("two"))
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("Vanity", "session-upload")
|
req.Header.Set("Vanity", "session-upload")
|
||||||
@@ -1733,7 +1733,7 @@ func TestUploadPageKeepsTheOneOffTokenField(t *testing.T) {
|
|||||||
// so anything the upload depends on has to be in the markup ahead of it. The
|
// so anything the upload depends on has to be in the markup ahead of it. The
|
||||||
// form is laid out to look otherwise, which is exactly why this is pinned: a
|
// form is laid out to look otherwise, which is exactly why this is pinned: a
|
||||||
// tidy-up that moves the drop zone back up in the markup would silently strip
|
// tidy-up that moves the drop zone back up in the markup would silently strip
|
||||||
// the expiry, the custom name and the one-off token from every upload.
|
// the expiry, the vanity name and the one-off token from every upload.
|
||||||
func TestUploadFormSendsTheFileLast(t *testing.T) {
|
func TestUploadFormSendsTheFileLast(t *testing.T) {
|
||||||
h := newHarness(t, nil)
|
h := newHarness(t, nil)
|
||||||
resp := h.get(t, "/", "")
|
resp := h.get(t, "/", "")
|
||||||
@@ -1757,10 +1757,10 @@ func TestUploadFormSendsTheFileLast(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anonymous visitors may type a custom name: the token that permits it can be
|
// Anonymous visitors may type a vanity name: the token that permits it can be
|
||||||
// supplied in the same form, for this upload only. The rule itself is the
|
// supplied in the same form, for this upload only. The rule itself is the
|
||||||
// server's to enforce, not the markup's.
|
// server's to enforce, not the markup's.
|
||||||
func TestCustomNameFieldIsAlwaysUsable(t *testing.T) {
|
func TestVanityFieldIsAlwaysUsable(t *testing.T) {
|
||||||
h := newHarness(t, nil)
|
h := newHarness(t, nil)
|
||||||
resp := h.get(t, "/", "")
|
resp := h.get(t, "/", "")
|
||||||
raw, _ := io.ReadAll(resp.Body)
|
raw, _ := io.ReadAll(resp.Body)
|
||||||
@@ -1768,9 +1768,9 @@ func TestCustomNameFieldIsAlwaysUsable(t *testing.T) {
|
|||||||
|
|
||||||
form := string(raw)
|
form := string(raw)
|
||||||
if i := strings.Index(form, `name="vanity"`); i < 0 {
|
if i := strings.Index(form, `name="vanity"`); i < 0 {
|
||||||
t.Fatal("the upload form has no custom name field")
|
t.Fatal("the upload form has no vanity name field")
|
||||||
} else if j := strings.Index(form[i:], ">"); strings.Contains(form[i:i+j], "disabled") {
|
} else if j := strings.Index(form[i:], ">"); strings.Contains(form[i:i+j], "disabled") {
|
||||||
t.Error("the custom name field is disabled, so a one-off token cannot be used with it")
|
t.Error("the vanity name field is disabled, so a one-off token cannot be used with it")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enabled in the page, still refused on the wire without a token.
|
// Enabled in the page, still refused on the wire without a token.
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ func (s *Server) storeUpload(w http.ResponseWriter, r *http.Request, req uploadR
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.vanity != "" && !lim.AllowVanity {
|
if req.vanity != "" && !lim.AllowVanity {
|
||||||
s.fail(w, r, http.StatusForbidden, "Custom names require a token.")
|
s.fail(w, r, http.StatusForbidden, "Vanity names require a token.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
expires, err := resolveExpiry(req.expiry, lim, now)
|
expires, err := resolveExpiry(req.expiry, lim, now)
|
||||||
@@ -220,7 +220,7 @@ func (s *Server) storeUpload(w http.ResponseWriter, r *http.Request, req uploadR
|
|||||||
return
|
return
|
||||||
case errors.Is(err, store.ErrBadID):
|
case errors.Is(err, store.ErrBadID):
|
||||||
s.fail(w, r, http.StatusBadRequest,
|
s.fail(w, r, http.StatusBadRequest,
|
||||||
"A custom name must be 2-64 characters of letters, digits, dot, dash or underscore.")
|
"A vanity name must be 2-64 characters of letters, digits, dot, dash or underscore.")
|
||||||
return
|
return
|
||||||
case err != nil:
|
case err != nil:
|
||||||
s.log.Error("reserving object", "err", err)
|
s.log.Error("reserving object", "err", err)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ keeps its current value. Give a limit an empty value to go back to inheriting
|
|||||||
the server's default, and turn a flag off with "=false":
|
the server's default, and turn a flag off with "=false":
|
||||||
|
|
||||||
uncensored-send token set friend --max-size= inherit the default again
|
uncensored-send token set friend --max-size= inherit the default again
|
||||||
uncensored-send token set friend --vanity=false revoke custom names
|
uncensored-send token set friend --vanity=false revoke vanity names
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
`
|
`
|
||||||
@@ -151,7 +151,7 @@ func (o *tokenOptions) register() *config.Set {
|
|||||||
fs.String(&o.defExpiry, "default-expiry", "", "", "DURATION", "lifetime applied when this token does not ask for one")
|
fs.String(&o.defExpiry, "default-expiry", "", "", "DURATION", "lifetime applied when this token does not ask for one")
|
||||||
fs.String(&o.chosen, "token", "t", "", "VALUE",
|
fs.String(&o.chosen, "token", "t", "", "VALUE",
|
||||||
"use this token instead of a generated one; \"-\" reads it from standard input")
|
"use this token instead of a generated one; \"-\" reads it from standard input")
|
||||||
fs.Bool(&o.vanity, "vanity", "", false, "allow this token to claim custom names; --vanity=false revokes it")
|
fs.Bool(&o.vanity, "vanity", "", false, "allow this token to claim vanity names; --vanity=false revokes it")
|
||||||
fs.Bool(&o.admin, "admin", "", false, "allow this token to delete anyone's files; --admin=false revokes it")
|
fs.Bool(&o.admin, "admin", "", false, "allow this token to delete anyone's files; --admin=false revokes it")
|
||||||
return fs
|
return fs
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td data-label="File" class="filecell">
|
<td data-label="File" class="filecell">
|
||||||
<a href="{{$.Base}}i/{{.ID}}">{{.Filename}}</a>
|
<a href="{{$.Base}}i/{{.ID}}">{{.Filename}}</a>
|
||||||
<span class="id mono">{{.ID}}{{if .Vanity}} <em title="custom name">★</em>{{end}}</span>
|
<span class="id mono">{{.ID}}{{if .Vanity}} <em title="vanity name">★</em>{{end}}</span>
|
||||||
</td>
|
</td>
|
||||||
<td data-label="Size" class="num nowrap">{{.Size}}</td>
|
<td data-label="Size" class="num nowrap">{{.Size}}</td>
|
||||||
<td data-label="Owner">{{if .Owner}}{{.Owner}}{{else}}<em>anonymous</em>{{end}}</td>
|
<td data-label="Owner">{{if .Owner}}{{.Owner}}{{else}}<em>anonymous</em>{{end}}</td>
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
<input type="text" name="expiry" id="expiry" placeholder="{{.ExpiryHint}}" autocomplete="off">
|
<input type="text" name="expiry" id="expiry" placeholder="{{.ExpiryHint}}" autocomplete="off">
|
||||||
</label>
|
</label>
|
||||||
<label class="field">
|
<label class="field">
|
||||||
<span>Custom name <em>({{if .AllowVanity}}optional{{else}}needs a token{{end}})</em></span>
|
<span>Vanity name <em>({{if .AllowVanity}}optional{{else}}needs a token{{end}})</em></span>
|
||||||
<input type="text" name="vanity" id="vanity" placeholder="auto" autocomplete="off"
|
<input type="text" name="vanity" id="vanity" placeholder="auto" autocomplete="off"
|
||||||
|
spellcheck="false" autocapitalize="off"
|
||||||
pattern="[A-Za-z0-9][A-Za-z0-9._-]{1,63}">
|
pattern="[A-Za-z0-9][A-Za-z0-9._-]{1,63}">
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -31,7 +32,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<label class="field">
|
<label class="field">
|
||||||
<span>Token</span>
|
<span>Token</span>
|
||||||
<input type="password" name="token" autocomplete="off">
|
<input type="password" name="token" autocomplete="new-password">
|
||||||
</label>
|
</label>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@@ -56,7 +57,7 @@
|
|||||||
<dt>Maximum size</dt><dd>{{.MaxSize}}</dd>
|
<dt>Maximum size</dt><dd>{{.MaxSize}}</dd>
|
||||||
<dt>Longest lifetime</dt><dd>{{.MaxExpiry}}</dd>
|
<dt>Longest lifetime</dt><dd>{{.MaxExpiry}}</dd>
|
||||||
<dt>Default lifetime</dt><dd>{{.DefaultExpiry}}</dd>
|
<dt>Default lifetime</dt><dd>{{.DefaultExpiry}}</dd>
|
||||||
<dt>Custom names</dt><dd>{{if .AllowVanity}}allowed{{else}}need a token{{end}}</dd>
|
<dt>Vanity names</dt><dd>{{if .AllowVanity}}allowed{{else}}need a token{{end}}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
{{if not .User}}<p class="hint"><a href="{{.Base}}login">Log in</a> with a token to raise these.</p>{{end}}
|
{{if not .User}}<p class="hint"><a href="{{.Base}}login">Log in</a> with a token to raise these.</p>{{end}}
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<dl>
|
<dl>
|
||||||
<dt>Maximum size</dt><dd>{{.MaxSize}}</dd>
|
<dt>Maximum size</dt><dd>{{.MaxSize}}</dd>
|
||||||
<dt>Longest lifetime</dt><dd>{{.MaxExpiry}}</dd>
|
<dt>Longest lifetime</dt><dd>{{.MaxExpiry}}</dd>
|
||||||
<dt>Custom names</dt><dd>{{if .Vanity}}allowed{{else}}not allowed{{end}}</dd>
|
<dt>Vanity names</dt><dd>{{if .Vanity}}allowed{{else}}not allowed{{end}}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<p class="actions">
|
<p class="actions">
|
||||||
<a class="button" href="{{.Base}}">Upload a file</a>
|
<a class="button" href="{{.Base}}">Upload a file</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user