{if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}).then(e=>{o?s.classList.add("apiperm-notgranted"):s.classList.add("apiperm-granted"),s.classList.remove("apiperm-processing")}).catch(e=>{o?s.classList.add("apiperm-granted"):s.classList.add("apiperm-notgranted"),s.classList.remove("apiperm-processing"),alert("Unable to set permission: "+e),console.error("Error:",e)})}function deleteApiKey(e){document.getElementById("delete-"+e).disabled=!0;var t="./api/auth/delete";const n={method:"POST",headers:{"Content-Type":"application/json",apikey:systemKey,apiKeyToModify:e}};fetch(t,n).then(e=>{if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}).then(t=>{document.getElementById("row-"+e).remove()}).catch(e=>{alert("Unable to delete API key: "+e),console.error("Error:",e)})}function newApiKey(){document.getElementById("button-newapi").disabled=!0;var e="./api/auth/create";const t={method:"POST",headers:{"Content-Type":"application/json",apikey:systemKey,basicPermissions:"true"}};fetch(e,t).then(e=>{if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}).then(e=>{location.reload()}).catch(e=>{alert("Unable to create API key: "+e),console.error("Error:",e)})}function deleteFile(e){document.getElementById("button-delete-"+e).disabled=!0;var t="./api/files/delete";const n={method:"POST",headers:{"Content-Type":"application/json",apikey:systemKey,id:e}};fetch(t,n).then(e=>{if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}).then(e=>{location.reload()}).catch(e=>{alert("Unable to delete file: "+e),console.error("Error:",e)})}function checkBoxChanged(e,t){let n=!e.checked;n?document.getElementById(t).setAttribute("disabled",""):document.getElementById(t).removeAttribute("disabled"),t==="password"&&n&&(document.getElementById("password").value="")}function parseData(e){return e?typeof e=="object"?e:typeof e=="string"?JSON.parse(e):{Result:"error"}:{Result:"error"}}function registerChangeHandler(){const e=new EventSource("./uploadStatus");e.onmessage=e=>{try{let t=JSON.parse(e.data);setProgressStatus(t.chunkid,t.currentstatus)}catch(e){console.error("Failed to parse event data:",e)}},e.onerror=t=>{t.target.readyState!==EventSource.CLOSED&&e.close(),console.log("Reconnecting to SSE..."),setTimeout(registerChangeHandler,5e3)}}statusItemCount=0;function addFileStatus(e,t){const n=document.createElement("div");n.setAttribute("id",`us-container-${e}`),n.classList.add("us-container");const a=document.createElement("div");a.classList.add("filename"),a.textContent=t,n.appendChild(a);const s=document.createElement("div");s.classList.add("upload-progress-container"),s.setAttribute("id",`us-progress-container-${e}`);const r=document.createElement("div");r.classList.add("upload-progress-bar");const o=document.createElement("div");o.setAttribute("id",`us-progressbar-${e}`),o.classList.add("upload-progress-bar-progress"),o.style.width="0%",r.appendChild(o);const i=document.createElement("div");i.setAttribute("id",`us-progress-info-${e}`),i.classList.add("upload-progress-info"),i.textContent="0%",s.appendChild(r),s.appendChild(i),n.appendChild(s),n.setAttribute("data-starttime",Date.now()),n.setAttribute("data-complete","false");const c=document.getElementById("uploadstatus");c.appendChild(n),c.style.visibility="visible",statusItemCount++}function removeFileStatus(e){const t=document.getElementById(`us-container-${e}`);if(t==null)return;t.remove(),statusItemCount--,statusItemCount<1&&(document.getElementById("uploadstatus").style.visibility="hidden")}function addRow(e){let r=parseData(e);if(r.Result!=="OK"){alert("Failed to upload file!"),location.reload();return}let t=r.FileInfo,p=document.getElementById("downloadtable"),s=p.insertRow(0);s.id="row-"+t.Id;let i=s.insertCell(0),a=s.insertCell(1),o=s.insertCell(2),c=s.insertCell(3),l=s.insertCell(4),d=s.insertCell(5),u=s.insertCell(6),h="";t.IsPasswordProtected===!0&&(h=' '),i.innerText=t.Name,i.id="cell-name-"+t.Id,a.innerText=t.Size,t.UnlimitedDownloads?o.innerText="Unlimited":o.innerText=t.DownloadsRemaining,t.UnlimitedTime?c.innerText="Unlimited":c.innerText=t.ExpireAtString,l.innerHTML="0",d.innerHTML=''+t.Id+""+h;let n=' ';t.UrlHotlink===""?n=n+' ':n=n+' ',n=n+' `,n=n+` ',n=n+'`,u.innerHTML=n,i.style.backgroundColor="green",a.style.backgroundColor="green",a.setAttribute("data-order",r.FileInfo.SizeBytes),o.style.backgroundColor="green",c.style.backgroundColor="green",l.style.backgroundColor="green",d.style.backgroundColor="green",u.style.backgroundColor="green";let m=$("#maintable").DataTable();rowCount==-1&&(rowCount=m.rows().count()),rowCount=rowCount+1,m.row.add(s);let f=document.getElementsByClassName("dataTables_empty")[0];return typeof f!="undefined"?f.innerText="Files stored: "+rowCount:document.getElementsByClassName("dataTables_info")[0].innerText="Files stored: "+rowCount,t.Id}function hideQrCode(){document.getElementById("qroverlay").style.display="none",document.getElementById("qrcode").innerHTML=""}function showQrCode(e){const t=document.getElementById("qroverlay");t.style.display="block",new QRCode(document.getElementById("qrcode"),{text:e,width:200,height:200,colorDark:"#000000",colorLight:"#ffffff",correctLevel:QRCode.CorrectLevel.H}),t.addEventListener("click",hideQrCode)}function showToast(){let e=document.getElementById("toastnotification");e.classList.add("show"),setTimeout(()=>{e.classList.remove("show")},1e3)}
\ No newline at end of file
diff --git a/internal/webserver/web/templates/html_admin.tmpl b/internal/webserver/web/templates/html_admin.tmpl
index 68a6812..08626c5 100644
--- a/internal/webserver/web/templates/html_admin.tmpl
+++ b/internal/webserver/web/templates/html_admin.tmpl
@@ -64,7 +64,7 @@
{{ range .Items }}
{{ if or (gt .ExpireAt $.TimeNow) (.UnlimitedTime) }}
{{ if or (gt .DownloadsRemaining 0) (.UnlimitedDownloads) }}
-
+
| {{ .Name }} |
{{ .Size }} |
{{ if .UnlimitedDownloads }}
@@ -87,7 +87,7 @@
{{ end }}
-
+
{{ end }}
{{ end }}
@@ -176,6 +176,7 @@
});
});
registerChangeHandler();
+ var systemKey = "{{.SystemKey}}";
{{ if .EndToEndEncryption }}
diff --git a/internal/webserver/web/templates/html_api.tmpl b/internal/webserver/web/templates/html_api.tmpl
index 97ab429..dd9835f 100644
--- a/internal/webserver/web/templates/html_api.tmpl
+++ b/internal/webserver/web/templates/html_api.tmpl
@@ -18,12 +18,13 @@
Last Used |
Permissions |
Actions |
- |
+ |
{{ range .ApiKeys }}
-
+{{ if not .IsSystemKey }}
+
| {{ .FriendlyName }} |
{{ .Id }} |
{{ .GetReadableDate }} |
@@ -31,19 +32,21 @@
-
+
- |
+ |
|
+{{ end }}
{{ end }}
+ API key copied to clipboard
@@ -69,6 +72,7 @@
xmlhttp.open("GET", "./api/auth/friendlyname");
xmlhttp.setRequestHeader("apiKeyToModify", row.id);
xmlhttp.setRequestHeader("friendlyName", val);
+ xmlhttp.setRequestHeader("apikey", systemKey);
xmlhttp.send();
row.classList.remove("isBeingEdited");
@@ -88,6 +92,7 @@
input.focus();
}
});
+ var systemKey = "{{.SystemKey}}";
{{ template "footer" true }}
{{ end }}
diff --git a/internal/webserver/web/templates/string_constants.tmpl b/internal/webserver/web/templates/string_constants.tmpl
index bd4784f..87d8f41 100644
--- a/internal/webserver/web/templates/string_constants.tmpl
+++ b/internal/webserver/web/templates/string_constants.tmpl
@@ -3,7 +3,7 @@
// Specifies the version of JS files, so that the browser doesn't
// use a cached version, if the file has been updated
-{{define "js_admin_version"}}5{{end}}
+{{define "js_admin_version"}}6{{end}}
{{define "js_dropzone_version"}}4{{end}}
{{define "js_e2eversion"}}3{{end}}
{{define "css_main"}}2{{end}}
\ No newline at end of file
diff --git a/openapi.json b/openapi.json
index 40a86a8..aa1fcd8 100644
--- a/openapi.json
+++ b/openapi.json
@@ -15,9 +15,6 @@
{
"apikey": ["VIEW","UPLOAD","DELETE", "API_MANAGE"]
},
- {
- "session": []
- }
],
"tags": [
{
@@ -40,9 +37,6 @@
{
"apikey": ["VIEW"]
},
- {
- "session": []
- }
],
"responses": {
"200": {
@@ -80,9 +74,6 @@
{
"apikey": ["UPLOAD"]
},
- {
- "session": []
- }
],
"requestBody": {
"content": {
@@ -126,9 +117,6 @@
{
"apikey": ["UPLOAD"]
},
- {
- "session": []
- }
],
"requestBody": {
"content": {
@@ -172,9 +160,6 @@
{
"apikey": ["UPLOAD"]
},
- {
- "session": []
- }
],
"requestBody": {
"content": {
@@ -218,9 +203,6 @@
{
"apikey": ["VIEW","UPLOAD"]
},
- {
- "session": []
- }
],
"requestBody": {
"content": {
@@ -264,9 +246,6 @@
{
"apikey": ["API_EDIT"]
},
- {
- "session": []
- }
],
"parameters": [
{
@@ -346,9 +325,6 @@
"security": [
{
"apikey": ["DELETE"]
- },
- {
- "session": []
}
],
"parameters": [
@@ -383,14 +359,11 @@
"auth"
],
"summary": "Creates a new API key",
- "description": "This API call returns a new API key. The new key does not have any permissions. Requires permission API_MOD",
+ "description": "This API call returns a new API key. The new key does not have any permissions, unless specified. Requires permission API_MOD",
"operationId": "create",
"security": [
{
"apikey": ["API_MANAGE"]
- },
- {
- "session": []
}
],
"parameters": [
@@ -404,6 +377,17 @@
"schema": {
"type": "string"
}
+ },
+ {
+ "name": "basicPermissions",
+ "in": "header",
+ "description": "If true, basic permissions are automatically granted",
+ "required": false,
+ "style": "simple",
+ "explode": false,
+ "schema": {
+ "type": "boolean"
+ }
}
],
"responses": {
@@ -434,9 +418,6 @@
"security": [
{
"apikey": ["API_MANAGE"]
- },
- {
- "session": []
}
],
"parameters": [
@@ -487,9 +468,6 @@
"security": [
{
"apikey": ["API_MANAGE"]
- },
- {
- "session": []
}
],
"parameters": [
@@ -541,6 +519,45 @@
}
}
}
+ },
+ "/auth/delete": {
+ "delete": {
+ "tags": [
+ "auth"
+ ],
+ "summary": "Deletes an API key",
+ "description": "This API call deletes the given API key. Requires permission API_MOD",
+ "operationId": "apidelete",
+ "security": [
+ {
+ "apikey": ["API_MANAGE"]
+ }
+ ],
+ "parameters": [
+ {
+ "name": "apiKeyToModify",
+ "in": "header",
+ "description": "The API key to delete",
+ "required": true,
+ "style": "simple",
+ "explode": false,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Operation successful"
+ },
+ "400": {
+ "description": "Invalid ID supplied"
+ },
+ "401": {
+ "description": "Invalid API key provided or not logged in as admin"
+ }
+ }
+ }
}
},
"components": {
@@ -812,11 +829,6 @@
"type": "apiKey",
"name": "apikey",
"in": "header"
- },
- "session": {
- "type": "apiKey",
- "name": "session_token",
- "in": "cookie"
}
}
}