Hotfix: user creation and other api url issues (#240)

This commit is contained in:
Graham Steffaniak 2024-11-21 10:58:28 -05:00 committed by GitHub
parent 9a011d3807
commit 21c9e321b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 45 additions and 33 deletions

View File

@ -2,6 +2,7 @@ package http
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"net/http" "net/http"
"reflect" "reflect"
@ -118,8 +119,16 @@ func userDeleteHandler(w http.ResponseWriter, r *http.Request, d *requestContext
num, _ := strconv.ParseUint(givenUserIdString, 10, 32) num, _ := strconv.ParseUint(givenUserIdString, 10, 32)
givenUserId := uint(num) givenUserId := uint(num)
if givenUserId == d.user.ID || !d.user.Perm.Admin { if givenUserId == d.user.ID {
return http.StatusForbidden, nil return http.StatusForbidden, fmt.Errorf("cannot delete your own user")
}
if !d.user.Perm.Admin {
return http.StatusForbidden, fmt.Errorf("cannot delete users without admin permissions")
}
if givenUserId == 1 {
return http.StatusForbidden, fmt.Errorf("cannot delete the default admin user")
} }
// Delete the user // Delete the user

View File

@ -1,6 +1,6 @@
import { createURL, fetchURL, adjustedData} from "./utils"; import { createURL, fetchURL, adjustedData} from "./utils";
import { baseURL } from "@/utils/constants"; import { baseURL } from "@/utils/constants";
import { removePrefix,getApiPath } from "@/utils/url.js"; import { removePrefix, getApiPath } from "@/utils/url.js";
import { state } from "@/store"; import { state } from "@/store";
import { notify } from "@/notify"; import { notify } from "@/notify";
@ -53,25 +53,18 @@ export async function put(url, content = "") {
export function download(format, ...files) { export function download(format, ...files) {
try { try {
let url = `${baseURL}/api/raw`; let path = "";
let fileargs = "";
if (files.length === 1) { if (files.length === 1) {
url += "?path="+removePrefix(files[0], "files"); path = removePrefix(files[0], "files")
} else { } else {
let arg = "";
for (let file of files) { for (let file of files) {
arg += removePrefix(file,"files") + ","; fileargs += removePrefix(file,"files") + ",";
} }
fileargs = fileargs.substring(0, fileargs.length - 1);
arg = arg.substring(0, arg.length - 1);
arg = encodeURIComponent(arg);
url += `?files=${arg}`;
} }
const apiPath = getApiPath("api/raw",{path: path, files: fileargs, algo: format});
if (format) { let url = `${baseURL}${apiPath}`;
url += `&algo=${format}`;
}
window.open(url); window.open(url);
} catch (err) { } catch (err) {
notify.showError(err.message || "Error downloading files"); notify.showError(err.message || "Error downloading files");

View File

@ -1,15 +1,17 @@
import { fetchURL, fetchJSON, createURL, adjustedData } from "./utils"; import { fetchURL, fetchJSON, createURL, adjustedData } from "./utils";
import { notify } from "@/notify"; import { notify } from "@/notify";
import { getApiPath } from "@/utils/url.js";
export async function list() { export async function list() {
return fetchJSON("api/shares"); const apiPath = getApiPath("api/shares");
return fetchJSON(apiPath);
} }
export async function get(path, hash) { export async function get(path, hash) {
try { try {
const params = { path, hash }; const params = { path, hash };
const url = createURL(`api/share`, params, false); const apiPath = getApiPath("api/share",params);
let data = fetchJSON(url); let data = fetchJSON(apiPath);
return adjustedData(data, `api/share${path}`); return adjustedData(data, `api/share${path}`);
} catch (err) { } catch (err) {
notify.showError(err.message || "Error fetching data"); notify.showError(err.message || "Error fetching data");
@ -19,25 +21,25 @@ export async function get(path, hash) {
export async function remove(hash) { export async function remove(hash) {
const params = { hash }; const params = { hash };
const url = createURL(`api/share`, params, false); const apiPath = getApiPath("api/share",params);
await fetchURL(url, { await fetchURL(apiPath, {
method: "DELETE", method: "DELETE",
}); });
} }
export async function create(path, password = "", expires = "", unit = "hours") { export async function create(path, password = "", expires = "", unit = "hours") {
const params = { path }; const params = { path };
const url = createURL(`api/share`, params, false); const apiPath = getApiPath("api/share",params);
let body = "{}"; let body = "{}";
if (password != "" || expires !== "" || unit !== "hours") { if (password != "" || expires !== "" || unit !== "hours") {
body = JSON.stringify({ password: password, expires: expires, unit: unit }); body = JSON.stringify({ password: password, expires: expires, unit: unit });
} }
return fetchJSON(url, { return fetchJSON(apiPath, {
method: "POST", method: "POST",
body: body, body: body,
}); });
} }
export function getShareURL(share) { export function getShareURL(share) {
return createURL("share/" + share.hash, {}, false); return createURL("share/"+share.hash, {}, false);
} }

View File

@ -60,7 +60,8 @@ export function deleteApiKey(params) {
export async function create(user) { export async function create(user) {
try { try {
const res = await fetchURL(`api/users`, { const apiPath = getApiPath("api/users");
const res = await fetchURL(apiPath, {
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify({
what: "user", what: "user",

View File

@ -24,9 +24,11 @@ export async function fetchURL(url, opts, auth = true) {
...rest, ...rest,
}); });
} catch (e) { } catch (e) {
console.error(e) let message = e;
const error = new Error("000 No connection"); if (e == "TypeError: Failed to fetch") {
error.status = res.status; message = "Failed to connect to the server, is it still running?";
}
const error = new Error(message);
throw error; throw error;
} }
@ -35,7 +37,7 @@ export async function fetchURL(url, opts, auth = true) {
} }
if (res.status < 200 || res.status > 299) { if (res.status < 200 || res.status > 299) {
const error = new Error(await res.text()); let error = new Error(await res.text());
error.status = res.status; error.status = res.status;
if (auth && res.status == 401) { if (auth && res.status == 401) {

View File

@ -16,7 +16,7 @@ export function showPopup(type, message) {
if (apiMessage && if (apiMessage &&
Object.prototype.hasOwnProperty.call(apiMessage, "status") && Object.prototype.hasOwnProperty.call(apiMessage, "status") &&
Object.prototype.hasOwnProperty.call(apiMessage, "message")) { Object.prototype.hasOwnProperty.call(apiMessage, "message")) {
popupContent.textContent = "Errors " + apiMessage.status + ": " + apiMessage.message; popupContent.textContent = "Error " + apiMessage.status + ": " + apiMessage.message;
} }
} catch (error) { } catch (error) {
popupContent.textContent = message; popupContent.textContent = message;

View File

@ -5,7 +5,7 @@
v-for="setting in settings" v-for="setting in settings"
:key="setting.id + '-main'" :key="setting.id + '-main'"
:id="setting.id + '-main'" :id="setting.id + '-main'"
@click="setView(setting.id + '-main')" @click="handleClick($event, setting.id + '-main')"
> >
<!-- Dynamically render the component based on the setting --> <!-- Dynamically render the component based on the setting -->
<component v-if="shouldShow(setting)" :is="setting.component"></component> <component v-if="shouldShow(setting)" :is="setting.component"></component>
@ -77,13 +77,18 @@ export default {
methods: { methods: {
shouldShow(setting) { shouldShow(setting) {
const perm = setting?.perm || {}; const perm = setting?.perm || {};
// Check if all keys in setting.perm exist in state.user.perm and have truthy values
return Object.keys(perm).every((key) => state.user.perm[key]); return Object.keys(perm).every((key) => state.user.perm[key]);
}, },
setView(view) { setView(view) {
if (state.activeSettingsView === view) return; if (state.activeSettingsView === view) return;
mutations.setActiveSettingsView(view); mutations.setActiveSettingsView(view);
}, },
handleClick(event, view) {
// Allow propagation if the click is on a link or a child element with default behavior
const target = event.target.closest("a, router-link");
if (target) return; // Let the browser/router handle the navigation
this.setView(view); // Call the setView method for other clicks
},
}, },
}; };
</script> </script>