这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ All notable changes to this project will be documented in this file. For commit
- Improved scrolling performance
- Static file handling has been streamlined, could potentially see some changes from this.

**BugFixes**:
- uploading/editing/saving to password protected shares error
- updating a share with password protection without a password removed the password.

## v1.0.1-stable

**BugFixes**:
Expand Down
1 change: 1 addition & 0 deletions backend/database/share/share.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type CommonShare struct {
DisableDownload bool `json:"disableDownload,omitempty"` // don't allow downloading files
AllowReplacements bool `json:"allowReplacements,omitempty"` // allow replacements of files
SidebarLinks []users.SidebarLink `json:"sidebarLinks"` // customizable sidebar links
HasPassword bool `json:"hasPassword,omitempty"`
}
type CreateBody struct {
CommonShare
Expand Down
1 change: 1 addition & 0 deletions backend/database/storage/bolt/share.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func (s shareBackend) GetCommonShareByHash(hash string) (*share.CommonShare, err
v.Path = ""
v.AllowedUsernames = nil
v.DownloadsLimit = 0
v.CommonShare.HasPassword = v.HasPassword()
return &v.CommonShare, nil
}

Expand Down
2 changes: 2 additions & 0 deletions backend/http/share.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ func convertToFrontendShareResponse(r *http.Request, shares []*share.Link) ([]*S
// Check if the path exists on the filesystem
pathExists := utils.CheckPathExists(filepath.Join(sourceInfo.Path, s.Path))

s.CommonShare.HasPassword = s.HasPassword()

// Create response with source name (overrides the embedded Link's source field)
responses = append(responses, &ShareResponse{
Link: s,
Expand Down
11 changes: 10 additions & 1 deletion frontend/src/api/public.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ export function post(
if (!hash || hash === undefined || hash === null) {
throw new Error('no hash provided')
}
let sharePassword = localStorage.getItem("sharepass:" + hash);
if (sharePassword) {
headers["X-SHARE-PASSWORD"] = sharePassword;
}
try {
const apiPath = getPublicApiPath("resources", {
targetPath: doubleEncode(path),
Expand All @@ -130,7 +134,6 @@ export function post(
for (const header in headers) {
request.setRequestHeader(header, headers[header]);
}

if (typeof onupload === "function") {
request.upload.onprogress = (event) => {
if (event.lengthComputable) {
Expand Down Expand Up @@ -181,11 +184,17 @@ export function post(

async function resourceAction(hash, path, method, content, token = "") {
try {
let headers = {};
let sharePassword = localStorage.getItem("sharepass:" + hash);
if (sharePassword) {
headers["X-SHARE-PASSWORD"] = sharePassword;
}
path = doubleEncode(path)
const apiPath = getPublicApiPath('resources', { path, hash: hash, token: token })
const response = await fetch(apiPath, {
method,
body: content,
headers,
});
if (!response.ok) {
const error = new Error(response.statusText);
Expand Down
68 changes: 65 additions & 3 deletions frontend/src/components/prompts/Share.vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
</div>
<div v-else>
<p>
{{ $t("time.unit") }}
{{ $t("files.duration") }}
<i class="no-select material-symbols-outlined tooltip-info-icon"
@mouseenter="showTooltip($event, $t('share.shareDurationDescription'))" @mouseleave="hideTooltip">
help
Expand All @@ -101,7 +101,13 @@
help
</i>
</p>
<input class="input" type="password" autocomplete="new-password" v-model.trim="password" />
<div v-if="hasExistingPassword && !isChangingPassword" class="password-change-section">
<button class="button button--flat button--blue" @click="isChangingPassword = true" style="width: 100%;">
<i class="material-icons">lock_reset</i>
{{ $t("general.change") }}
</button>
</div>
<input v-else class="input" type="password" autocomplete="new-password" v-model.trim="password" />
<p>
{{ $t("share.shareType") }}
<i class="no-select material-symbols-outlined tooltip-info-icon"
Expand Down Expand Up @@ -391,6 +397,7 @@ export default {
tempPath: "",
tempSource: "",
pathExists: true,
isChangingPassword: false,
//viewMode: "normal",
};
},
Expand Down Expand Up @@ -444,12 +451,18 @@ export default {
},
isEditMode() {
return this.editing && this.link && Object.keys(this.link).length > 0;
},
hasExistingPassword() {
// Check if we're editing a link and it has a password
const currentLink = this.isEditMode ? this.link : this.editingLink;
return currentLink && currentLink.hasPassword;
}
},
watch: {
listing(isListing) {
if (!isListing) {
this.password = "";
this.isChangingPassword = false;
}
},
isEditMode: {
Expand All @@ -464,6 +477,7 @@ export default {
: "0";
this.unit = "hours";
this.password = "";
this.isChangingPassword = false;
this.disableDownload = this.link.disableDownload || false;
this.allowModify = this.link.allowModify || false;
this.allowDelete = this.link.allowDelete || false;
Expand Down Expand Up @@ -515,6 +529,8 @@ export default {

if (this.links.length === 0) {
this.listing = false;
// Set default sidebar links for new shares
this.setDefaultSidebarLinks();
}
},
mounted() {
Expand Down Expand Up @@ -574,7 +590,6 @@ export default {
const payload = {
path: this.displayPath,
source: this.displaySource,
password: this.password,
expires: isPermanent ? "" : this.time.toString(),
unit: this.unit,
disableAnonymous: this.disableAnonymous,
Expand Down Expand Up @@ -608,6 +623,15 @@ export default {
extractEmbeddedSubtitles: this.extractEmbeddedSubtitles,
sidebarLinks: this.sidebarLinks,
};

// Handle password inclusion logic:
// - Always include for new shares
// - For editing: only include if no existing password OR explicitly changing it
const isEditing = this.isEditMode || this.editingLink;
if (!isEditing || !this.hasExistingPassword || this.isChangingPassword) {
payload.password = this.password;
}

if (this.isEditMode) {
payload.hash = this.link.hash;
} else if (this.editingLink) {
Expand Down Expand Up @@ -645,6 +669,7 @@ export default {
this.time = "";
this.unit = "hours";
this.password = "";
this.isChangingPassword = false;

this.listing = true;
} catch (err) {
Expand All @@ -664,6 +689,7 @@ export default {
: "0";
this.unit = "hours";
this.password = "";
this.isChangingPassword = false;
this.disableDownload = link.disableDownload || false;
this.allowModify = link.allowModify || false;
this.allowDelete = link.allowDelete || false;
Expand Down Expand Up @@ -768,6 +794,31 @@ export default {
// Clear editing link when switching back to listing
if (this.listing) {
this.editingLink = null;
} else {
// Clear editing link when switching to create new share
this.editingLink = null;
this.isChangingPassword = false;
// Set default sidebar links for new shares
this.setDefaultSidebarLinks();
}
},
setDefaultSidebarLinks() {
// Only set defaults if creating a new share (not editing) and no links are configured
if (!this.isEditMode && !this.editingLink && this.sidebarLinks.length === 0) {
this.sidebarLinks = [
{
name: "Share QR Code and Info",
category: "shareInfo",
target: "#",
icon: "qr_code"
},
{
name: "Download",
category: "download",
target: "#",
icon: "download"
}
];
}
},
fixDownloadURL(downloadUrl) {
Expand Down Expand Up @@ -856,4 +907,15 @@ export default {
.input {
height: auto;
}

.password-change-section {
margin-bottom: 1em;
}

.password-change-section button {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5em;
}
</style>
26 changes: 19 additions & 7 deletions frontend/src/components/sidebar/Links.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<template>
<transition name="expand" @before-enter="beforeEnter" @enter="enter" @leave="leave">
<div v-if="true" class="sidebar-links card">
<div class="sidebar-links-header">
<i @click="goHome()" class="material-icons action">home</i>
<div v-if="!isShare || hasLinks" class="sidebar-links card">
<div class="sidebar-links-header" :class="{ 'no-edit-options': isShare }">
<i v-if="!isShare" @click="goHome()" class="material-icons action">home</i>
<span>{{ $t("general.links") }}</span>
<i @mouseenter="showTooltip($event, $t('sidebar.customizeLinks'))" @mouseleave="hideTooltip"
<i v-if="!isShare" @mouseenter="showTooltip($event, $t('sidebar.customizeLinks'))" @mouseleave="hideTooltip"
@click="openSidebarLinksPrompt" class="material-icons action">edit</i>
</div>
<transition-group name="expand" tag="div" class="inner-card">
Expand Down Expand Up @@ -64,13 +64,18 @@ import { goToItem } from "@/utils/url";
import { getIconClass } from "@/utils/material-icons";
import { buildIndexInfoTooltipHTML } from "@/components/files/IndexInfo.vue";
import { globalVars } from "@/utils/constants";
import { publicApi } from "@/api";

export default {
name: "SidebarLinks",
components: {
ProgressBar,
},
computed: {
isShare: () => getters.isShare(),
hasLinks() {
return this.sidebarLinksToDisplay?.length > 0;
},
user: () => (state.user || {username: 'anonymous'}),
sourceInfo: () => state.sources.info,
activeSource: () => state.sources.current,
Expand Down Expand Up @@ -186,8 +191,10 @@ export default {
}
},
goToDownload() {
const { publicApi } = require("@/api");
if (state.req.items.length > 1) {
// Check if we're in a directory with multiple items
const hasMultipleItems = state.req.items && state.req.items.length > 1;
if (hasMultipleItems) {
// Show format selector for directories with multiple items
mutations.showHover({
name: "download",
confirm: (format) => {
Expand All @@ -202,6 +209,7 @@ export default {
},
});
} else {
// Direct download for single files or directories
const downloadLink = publicApi.getDownloadURL({
path: "/",
hash: state.share.hash,
Expand Down Expand Up @@ -282,14 +290,18 @@ export default {

<style scoped>

.no-edit-options {
justify-content: center !important;
}

.usage-info .vue-simple-progress {
border-style: solid;
border-color: var(--surfaceSecondary);
}

.sidebar-links {
padding: 1em;
overflow: scroll;
overflow: auto;
}

.material-icons.action {
Expand Down
15 changes: 14 additions & 1 deletion frontend/src/components/sidebar/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
hidden: !shouldShow(setting),
'active-settings': active(setting.id + '-main'),
}">
<span v-if="shouldShow(setting)" >{{ $t(setting.label) }}</span>
<span v-if="shouldShow(setting)" class="settings-item-content">
<span class="material-symbols-outlined settings-icon">{{ setting.icon }}</span>
{{ $t(setting.label) }}
</span>
</div>
</template>

Expand Down Expand Up @@ -64,4 +67,14 @@ export default {
overflow: unset !important;
padding: 1em;
}

.settings-item-content {
display: flex;
align-items: center;
gap: 0.5em;
}

.settings-icon {
font-size: 1.2em;
}
</style>
3 changes: 2 additions & 1 deletion frontend/src/i18n/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,8 @@
"commands": "الأوامر{suffix}",
"uploading": "التحميل{suffix}",
"paused": "متوقف مؤقتاً{suffix}",
"conflict": "التعارض{suffix}"
"conflict": "التعارض{suffix}",
"change": "التغيير{suffix}"
},
"access": {
"rules": "قواعد الوصول",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/i18n/cz.json
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,8 @@
"commands": "Příkazy{suffix}",
"uploading": "Nahrávání{suffix}",
"paused": "Pauza{suffix}",
"conflict": "Konflikt{suffix}"
"conflict": "Konflikt{suffix}",
"change": "Změna{suffix}"
},
"access": {
"rules": "Pravidla přístupu",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,8 @@
"commands": "Befehle{suffix}",
"uploading": "Hochladen{suffix}",
"paused": "Pausiert{suffix}",
"conflict": "Konflikt{suffix}"
"conflict": "Konflikt{suffix}",
"change": "Ändern Sie{suffix}"
},
"access": {
"rules": "Zugangsregeln",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/i18n/el.json
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,8 @@
"commands": "Εντολές{suffix}",
"uploading": "Ανέβασμα{suffix}",
"paused": "Παύση{suffix}",
"conflict": "Σύγκρουση{suffix}"
"conflict": "Σύγκρουση{suffix}",
"change": "Αλλαγή{suffix}"
},
"access": {
"rules": "Κανόνες πρόσβασης",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"add": "Add{suffix}",
"stay": "Stay{suffix}",
"cancel": "Cancel{suffix}",
"change": "Change{suffix}",
"verify": "Verify{suffix}",
"close": "Close{suffix}",
"copy": "Copy{suffix}",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,8 @@
"commands": "Comandos{suffix}",
"uploading": "Cargar{suffix}",
"paused": "En pausa{suffix}",
"conflict": "Conflicto{suffix}"
"conflict": "Conflicto{suffix}",
"change": "Cambia{suffix}"
},
"access": {
"rules": "Normas de acceso",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,8 @@
"commands": "Commandes{suffix}",
"uploading": "Téléchargement{suffix}",
"paused": "En pause{suffix}",
"conflict": "Conflit{suffix}"
"conflict": "Conflit{suffix}",
"change": "Changer{suffix}"
},
"access": {
"rules": "Règles d'accès",
Expand Down
Loading
Loading