Merge remote-tracking branch 'origin/master' into 0.2-dev
This commit is contained in:
commit
a6d69c319e
|
@ -21,6 +21,11 @@ allow_pass_protection=true
|
||||||
# This is shown only if allow_uploads = false
|
# This is shown only if allow_uploads = false
|
||||||
# upload_disable_reason="File uploads were disabled because of an ongoing attack."
|
# upload_disable_reason="File uploads were disabled because of an ongoing attack."
|
||||||
|
|
||||||
|
# If you want to restrict the uploads
|
||||||
|
# To only the people who have a password,
|
||||||
|
# uncomment this field
|
||||||
|
# upload_pass=super_secret_pass
|
||||||
|
|
||||||
# Timeout for deleting a user uploaded file
|
# Timeout for deleting a user uploaded file
|
||||||
file_del_timeout=1800
|
file_del_timeout=1800
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,10 @@ paths:
|
||||||
type: string
|
type: string
|
||||||
example: binary file data
|
example: binary file data
|
||||||
description: binary file data
|
description: binary file data
|
||||||
|
instance_pass:
|
||||||
|
type: string
|
||||||
|
example: super_secret_pass
|
||||||
|
description: Instance-specific password needed to upload files
|
||||||
metadata:
|
metadata:
|
||||||
type: object
|
type: object
|
||||||
description: file info
|
description: file info
|
||||||
|
|
|
@ -22,6 +22,10 @@ pub struct FilesPolicy {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub upload_disable_reason: Option<String>,
|
pub upload_disable_reason: Option<String>,
|
||||||
|
|
||||||
|
/// Upload password
|
||||||
|
#[serde(default)]
|
||||||
|
pub upload_pass: Option<String>,
|
||||||
|
|
||||||
/// Default time for file to be deleted
|
/// Default time for file to be deleted
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub file_del_timeout: usize,
|
pub file_del_timeout: usize,
|
||||||
|
@ -42,6 +46,7 @@ impl Default for FilesPolicy {
|
||||||
allow_custom_names: true,
|
allow_custom_names: true,
|
||||||
allow_pass_protection: true,
|
allow_pass_protection: true,
|
||||||
upload_disable_reason: None,
|
upload_disable_reason: None,
|
||||||
|
upload_pass: None,
|
||||||
file_del_timeout: 1800,
|
file_del_timeout: 1800,
|
||||||
type_whitelist: None,
|
type_whitelist: None,
|
||||||
type_blacklist: None,
|
type_blacklist: None,
|
||||||
|
|
|
@ -61,6 +61,7 @@ impl FormElement {
|
||||||
struct UploadFormData {
|
struct UploadFormData {
|
||||||
filename: Option<String>,
|
filename: Option<String>,
|
||||||
password: Option<String>,
|
password: Option<String>,
|
||||||
|
instancepass: Option<String>,
|
||||||
lookup_kind: LookupKind,
|
lookup_kind: LookupKind,
|
||||||
delmode: DeleteMode,
|
delmode: DeleteMode,
|
||||||
file: Vec<u8>,
|
file: Vec<u8>,
|
||||||
|
@ -73,6 +74,7 @@ impl Default for UploadFormData {
|
||||||
UploadFormData {
|
UploadFormData {
|
||||||
filename: None,
|
filename: None,
|
||||||
password: None,
|
password: None,
|
||||||
|
instancepass: None,
|
||||||
lookup_kind: LookupKind::ByHash,
|
lookup_kind: LookupKind::ByHash,
|
||||||
delmode: DeleteMode::Time,
|
delmode: DeleteMode::Time,
|
||||||
file: vec![],
|
file: vec![],
|
||||||
|
@ -127,6 +129,16 @@ impl UploadFormData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match data.get("instancepass") {
|
||||||
|
Some(val) => {
|
||||||
|
let val = val.data.clone();
|
||||||
|
if let Ok(pass) = String::from_utf8(val) {
|
||||||
|
out.instancepass = Some(pass);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => ()
|
||||||
|
};
|
||||||
|
|
||||||
let file = data.get("file")?;
|
let file = data.get("file")?;
|
||||||
out.file = file.data.clone();
|
out.file = file.data.clone();
|
||||||
out.mime = file.mime.clone();
|
out.mime = file.mime.clone();
|
||||||
|
@ -201,6 +213,47 @@ pub async fn upload(form: FormData, ip: Option<IpAddr>, state: SharedState) -> R
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(upload_pass) = state.config.files.upload_pass.clone() {
|
||||||
|
|
||||||
|
if let Some(pass) = formdata.instancepass {
|
||||||
|
if upload_pass != pass {
|
||||||
|
let error = ErrorPage {
|
||||||
|
env: state.env.clone(),
|
||||||
|
conf: state.config.clone(),
|
||||||
|
error_text: "Password is invalid".into(),
|
||||||
|
link: Some("/".into()),
|
||||||
|
link_text: Some("Go back".into())
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(
|
||||||
|
Box::new(
|
||||||
|
html(
|
||||||
|
error.render()
|
||||||
|
.map_err(|x| HttpReject::AskamaError(x))?
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let error = ErrorPage {
|
||||||
|
env: state.env.clone(),
|
||||||
|
conf: state.config.clone(),
|
||||||
|
error_text: "Password is not available".into(),
|
||||||
|
link: Some("/".into()),
|
||||||
|
link_text: Some("Go back".into())
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(
|
||||||
|
Box::new(
|
||||||
|
html(
|
||||||
|
error.render()
|
||||||
|
.map_err(|x| HttpReject::AskamaError(x))?
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let file = File::create(
|
let file = File::create(
|
||||||
formdata.file,
|
formdata.file,
|
||||||
formdata.mime,
|
formdata.mime,
|
||||||
|
|
|
@ -21,3 +21,7 @@
|
||||||
.alert.danger .alert-title {
|
.alert.danger .alert-title {
|
||||||
background: #602020;
|
background: #602020;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alert.blue .alert-title {
|
||||||
|
background: #203050;
|
||||||
|
}
|
|
@ -9,6 +9,31 @@
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
|
||||||
|
{%- if conf.files.upload_pass.is_some() -%}
|
||||||
|
|
||||||
|
{#- Script to disable button when password is not entered -#}
|
||||||
|
{#- -#}<script>
|
||||||
|
{#- -#} (
|
||||||
|
{#- -#} ()=>{
|
||||||
|
{#- -#} const pass_inp=document.getElementById("instancepass");
|
||||||
|
{#- -#} const submit=document.getElementById("bfile-upload-submit");
|
||||||
|
{#- -#} submit.setAttribute('disabled',true);
|
||||||
|
{#- -#}
|
||||||
|
{#- -#} pass_inp.onchange=()=>{
|
||||||
|
{#- -#} if(pass_inp.value.length==0)
|
||||||
|
{#- -#} submit.setAttribute('disabled',true);
|
||||||
|
{#- -#} else submit.removeAttribute('disabled')
|
||||||
|
{#- -#} }
|
||||||
|
{#- -#} }
|
||||||
|
{#- -#} )()
|
||||||
|
{#- -#}</script>
|
||||||
|
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
|
||||||
<div style="max-width:95vw;width:fit-content;margin:0 auto">
|
<div style="max-width:95vw;width:fit-content;margin:0 auto">
|
||||||
|
@ -114,6 +139,24 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{%- else -%}
|
{%- else -%}
|
||||||
|
|
||||||
|
{%- if let Some(pass) = conf.files.upload_pass -%}
|
||||||
|
<div class="alert blue">
|
||||||
|
<h1 class="alert-title">
|
||||||
|
Upload password
|
||||||
|
</h1>
|
||||||
|
<div class="alert-text">
|
||||||
|
<p>This instance requires a password to upload a file.</p>
|
||||||
|
<p>
|
||||||
|
<label>
|
||||||
|
Password:
|
||||||
|
<input type="password" name="instancepass" id="instancepass">
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<input type="file" name="file" id="bfile-formupload-file" style="display: none" />
|
<input type="file" name="file" id="bfile-formupload-file" style="display: none" />
|
||||||
<label for="bfile-formupload-file">
|
<label for="bfile-formupload-file">
|
||||||
|
@ -142,7 +185,7 @@
|
||||||
</label>
|
</label>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<button class='btn btn-fill'>
|
<button class='btn btn-fill' id="bfile-upload-submit">
|
||||||
Upload!
|
Upload!
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
|
|
Loading…
Reference in New Issue