feat: allow specifying api token in nojs uploader

This commit is contained in:
Bobby 2022-09-21 08:03:28 +07:00
parent 7147afc309
commit 47727f3ca8
No known key found for this signature in database
GPG Key ID: 941839794CBF5A09
3 changed files with 44 additions and 24 deletions

View File

@ -4,6 +4,7 @@ const fs = require('fs')
const path = require('path')
const randomstring = require('randomstring')
const searchQuery = require('search-query-parser')
const auth = require('./authController')
const paths = require('./pathsController')
const perms = require('./permissionController')
const utils = require('./utilsController')
@ -263,12 +264,16 @@ self.parseStripTags = stripTags => {
/** File uploads */
self.upload = async (req, res) => {
// Assert Request type
// Multipart for regular uploads, JSON for URL uploads
const isMultipart = req.is('multipart/form-data')
const isJson = req.is('application/json')
if (!isMultipart && !isJson) {
throw new ClientError('Request Content-Type must be either multipart/form-data or application/json.')
// Assert Request type (skip for POST /nojs requests)
let isMultipart = req.locals.nojs
let isJson
if (!req.locals.nojs) {
// Multipart for regular uploads, JSON for URL uploads
isMultipart = req.is('multipart/form-data')
isJson = req.is('application/json')
if (!isMultipart && !isJson) {
throw new ClientError('Request Content-Type must be either multipart/form-data or application/json.')
}
}
if (config.privateUploadGroup) {
@ -513,6 +518,18 @@ self.actuallyUpload = async (req, res, data = {}) => {
return res.json({ success: true })
}
// If POST /nojs requests, additionally attempt to parse token from form input
if (req.locals.nojs) {
await new Promise((resolve, reject) => {
auth.optionalUser(req, res, error => {
if (error) return reject(error)
return resolve()
}, {
token: req.body.token
})
})
}
const filesData = req.files
if (utils.scan.instance) {

View File

@ -11,9 +11,16 @@ routes.get('/nojs', async (req, res) => {
})
// HyperExpress defaults to 250kb
// https://github.com/kartikk221/hyper-express/blob/6.4.4/docs/Server.md#server-constructor-options
const maxBodyLength = parseInt(config.uploads.maxSize) * 1e6
routes.post('/nojs', { max_body_length: maxBodyLength }, async (req, res) => {
// https://github.com/kartikk221/hyper-express/blob/6.4.8/docs/Server.md#server-constructor-options
routes.post('/nojs', {
max_body_length: parseInt(config.uploads.maxSize) * 1e6,
middlewares: [
async (req, res) => {
// Assert Request type early
utils.assertRequestType(req, 'multipart/form-data')
}
]
}, async (req, res) => {
// Map built-in Response.json() function into Response.render() accordingly
// Since NoJS uploader needs to reply with a complete HTML page
res._json = res.json
@ -27,6 +34,11 @@ routes.post('/nojs', { max_body_length: maxBodyLength }, async (req, res) => {
files: result.files || [{}]
})
}
// Indicate uploadController.js to additionally process this request further
// (skip request type assertion, parse token from form input, etc.)
req.locals.nojs = true
return upload.upload(req, res)
})

View File

@ -3,14 +3,6 @@
{% extends "_layout.njk" %}
{% set private = config.private %}
{% set disabledMessage -%}
{%- if config.enableUserAccounts -%}
Anonymous upload is disabled. Log in to upload.
{%- else -%}
Running in private mode. Log in to upload.
{%- endif %}
{%- endset %}
{% set maxSizeInt = config.uploads.maxSize | int %}
{% set noJsMaxSizeInt = config.cloudflare.noJsMaxSize | int %}
@ -37,27 +29,26 @@
<div class="columns is-gapless">
<div class="column is-hidden-mobile"></div>
<div class="column">
{% if private -%}
<a class="button is-danger is-outlined is-fullwidth" href="auth">
{{ disabledMessage }}
</a>
{%- else -%}
<form id="form" class="field" action="" method="post" enctype="multipart/form-data">
<div class="field">
<p class="control">
<input type="file" class="is-fullwidth" name="files[]" multiple="multiple" required="required">
</p>
</div>
<div class="field">
<p class="control">
<input type="text" class="input is-fullwidth" name="token" minLength="64" maxLength="64" placeholder="API token ({{ "required" if config.private else "optional"}})"{% if config.private %} required="required"{% endif %}>
</p>
</div>
<div class="field">
<p class="control">
<input type="submit" class="button is-danger is-outlined is-fullwidth" value="Upload">
</p>
<p class="help">
Files uploaded through this form will not be associated with your account, if you have any.
Files uploaded through this form will only be associated with your account if you specify your API token.
</p>
</div>
</form>
{%- endif %}
{% if files -%}
<div class="field uploads nojs">
{% for file in files -%}