Compare commits
35
Commits
main
...
stable/v1.0.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c8843b766 | ||
|
|
337b958b9e | ||
|
|
dc60832d22 | ||
|
|
809e1e5ea4 | ||
|
|
75c8d7847f | ||
|
|
07f37cb3a6 | ||
|
|
403614dcb3 | ||
|
|
e0d9ff25da | ||
|
|
55620b5056 | ||
|
|
f4f2400d91 | ||
|
|
f6b4310035 | ||
|
|
095bdff589 | ||
|
|
6baa5d1b73 | ||
|
|
01569dfa88 | ||
|
|
67ff16e2a6 | ||
|
|
02f28b53bb | ||
|
|
138c4a99b5 | ||
|
|
30d2e8ab44 | ||
|
|
f48156a8fe | ||
|
|
8371e7a2d8 | ||
|
|
6d33057cac | ||
|
|
3f6e9af56c | ||
|
|
2c3bef143a | ||
|
|
9871d27cb7 | ||
|
|
60780c91c6 | ||
|
|
8fa1438ff9 | ||
|
|
39bbf69911 | ||
|
|
b953957c96 | ||
|
|
79ead3997e | ||
|
|
53c4fa586f | ||
|
|
92168ed471 | ||
|
|
0941f17f8f | ||
|
|
dfaccd8e34 | ||
|
|
f33d058a12 | ||
|
|
e31f4e9c7c |
No files matched your search
+16
-1
@@ -2,7 +2,18 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. For commit guidelines, please refer to [Standard Version](https://github.com/conventional-changelog/standard-version).
|
||||
|
||||
## v1.0.1
|
||||
## v1.0.1-stable
|
||||
|
||||
**BugFixes**:
|
||||
- UserDefault always applies to newly created users #1518
|
||||
- Updating user's own password sometimes doesn't work
|
||||
- Anonymous Share link with optional password does not allow downloads #1553
|
||||
- Share options should go in the meta tags #1511
|
||||
- Unable to select compression format when downloading multiple files/dir via Share link (v1.0.0) #1557
|
||||
- fixed sidebar clipping on some browsers like safari
|
||||
- Files show as Download is not available even though it is #1537
|
||||
|
||||
## v1.0.1-beta & v1.0.0-stable
|
||||
|
||||
**New Features**:
|
||||
- login icon support added via `frontend.loginIcon` config path variable
|
||||
@@ -27,7 +38,11 @@ All notable changes to this project will be documented in this file. For commit
|
||||
- fixed some condition that the halloween background doesn't load properly
|
||||
- some comments not showing up on config viewer in settings
|
||||
|
||||
<<<<<<< HEAD
|
||||
## v1.0.0-beta
|
||||
=======
|
||||
## v1.0.0
|
||||
>>>>>>> main
|
||||
|
||||
**Notes**:
|
||||
- Enhanced onlyoffice debugger with more wholistic backend logs
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ RUN go build -tags mupdf,musl -ldflags="-w -s \
|
||||
-o filebrowser .
|
||||
RUN upx filebrowser
|
||||
|
||||
FROM node:lts-slim AS nbuild
|
||||
FROM node:jod-slim AS nbuild
|
||||
WORKDIR /app
|
||||
COPY ./frontend/package.json ./
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates \
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ func runCLI() bool {
|
||||
}
|
||||
newUser.Permissions = settings.Config.UserDefaults.Permissions
|
||||
newUser.Permissions.Admin = asAdmin
|
||||
err = storage.CreateUser(newUser)
|
||||
err = storage.CreateUser(newUser, newUser.Permissions)
|
||||
if err != nil {
|
||||
logger.Errorf("could not create user: %v", err)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gtsteffaniak/filebrowser/backend/common/settings"
|
||||
"github.com/gtsteffaniak/filebrowser/backend/common/version"
|
||||
"github.com/gtsteffaniak/go-logger/logger"
|
||||
"golang.org/x/mod/semver"
|
||||
@@ -30,6 +31,9 @@ func CheckForUpdates() (updateInfo, error) {
|
||||
repoOwner := "gtsteffaniak"
|
||||
repoName := "filebrowser"
|
||||
currentVersion := version.Version
|
||||
if currentVersion == "untracked" || currentVersion == "testing" || currentVersion == "" || settings.Config.Env.IsDevMode {
|
||||
return updateInfo{}, nil
|
||||
}
|
||||
splitVersion := strings.Split(currentVersion, "-")
|
||||
versionCategory := "stable"
|
||||
if len(splitVersion) > 1 {
|
||||
@@ -51,13 +55,13 @@ func CheckForUpdates() (updateInfo, error) {
|
||||
if err := json.NewDecoder(resp.Body).Decode(&tags); err != nil {
|
||||
return updateInfo{}, err
|
||||
}
|
||||
// Find the latest beta version greater than the current one
|
||||
// Find the latest version greater than the current one that matches the version category
|
||||
var NewVersion string
|
||||
for _, tag := range tags {
|
||||
// Check if the version is valid, is a pre-release, and contains "beta"
|
||||
// Check if the version is valid and the prerelease contains the version category
|
||||
if semver.IsValid(tag.Name) && strings.Contains(semver.Prerelease(tag.Name), versionCategory) {
|
||||
// Check if this tag is greater than the current version
|
||||
// and also greater than any other beta version we've found so far
|
||||
// and also greater than any other version we've found so far
|
||||
if semver.Compare(tag.Name, currentVersion) > 0 {
|
||||
if NewVersion == "" || semver.Compare(tag.Name, NewVersion) > 0 {
|
||||
NewVersion = tag.Name
|
||||
|
||||
@@ -84,6 +84,10 @@ func (st usersBackend) Update(user *users.User, actorIsAdmin bool, fields ...str
|
||||
return err
|
||||
}
|
||||
|
||||
if user.LoginMethod == "" {
|
||||
user.LoginMethod = existingUser.LoginMethod
|
||||
}
|
||||
|
||||
if !slices.Contains(fields, "Password") {
|
||||
user.Password = existingUser.Password
|
||||
} else {
|
||||
|
||||
@@ -107,7 +107,7 @@ func quickSetup(store *bolt.BoltStore) {
|
||||
}
|
||||
|
||||
// create new user
|
||||
func CreateUser(userInfo users.User) error {
|
||||
func CreateUser(userInfo users.User, permissions users.Permissions) error {
|
||||
newUser := &userInfo
|
||||
newUser.ShowFirstLogin = settings.Config.Env.IsFirstLoad && newUser.Permissions.Admin
|
||||
if userInfo.LoginMethod == "password" {
|
||||
@@ -125,6 +125,8 @@ func CreateUser(userInfo users.User) error {
|
||||
if userInfo.Username == "" {
|
||||
return fmt.Errorf("username is required to create a user")
|
||||
}
|
||||
settings.ApplyUserDefaults(newUser)
|
||||
newUser.Permissions = permissions
|
||||
logger.Debugf("Creating user: %v %v", userInfo.Username, userInfo.Scopes)
|
||||
// create new home directories
|
||||
err := userStore.Save(newUser, true, false)
|
||||
|
||||
@@ -84,7 +84,7 @@ func setupProxyUser(r *http.Request, data *requestContext, proxyUser string) (*u
|
||||
if user.Username == config.Auth.AdminUsername {
|
||||
user.Permissions.Admin = true
|
||||
}
|
||||
err = storage.CreateUser(user)
|
||||
err = storage.CreateUser(user, user.Permissions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -223,8 +223,7 @@ func signupHandler(w http.ResponseWriter, r *http.Request, d *requestContext) (i
|
||||
},
|
||||
LoginMethod: users.LoginMethodPassword,
|
||||
}
|
||||
user.Permissions = settings.Config.UserDefaults.Permissions
|
||||
err := storage.CreateUser(user)
|
||||
err := storage.CreateUser(user, settings.Config.UserDefaults.Permissions)
|
||||
if err != nil {
|
||||
logger.Debug(err.Error())
|
||||
// Return the actual error message instead of a generic one
|
||||
|
||||
@@ -300,7 +300,7 @@ func loginWithOidcUser(w http.ResponseWriter, r *http.Request, username string,
|
||||
if isAdmin {
|
||||
user.Permissions.Admin = true
|
||||
}
|
||||
err = storage.CreateUser(*user)
|
||||
err = storage.CreateUser(*user, user.Permissions)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
+12
-4
@@ -70,6 +70,8 @@ func handleWithStaticData(w http.ResponseWriter, r *http.Request, d *requestCont
|
||||
|
||||
defaultThemeColor := "#455a64"
|
||||
staticURL := config.Server.BaseURL + "public/static"
|
||||
description := config.Frontend.Description
|
||||
title := config.Frontend.Name
|
||||
|
||||
// Use custom favicon if configured and validated, otherwise fall back to default
|
||||
var favicon string
|
||||
@@ -148,10 +150,16 @@ func handleWithStaticData(w http.ResponseWriter, r *http.Request, d *requestCont
|
||||
}
|
||||
}
|
||||
if d.share.Description != "" {
|
||||
data["description"] = d.share.Description
|
||||
description = d.share.Description
|
||||
}
|
||||
if d.share.Title != "" {
|
||||
data["title"] = d.share.Title
|
||||
title = d.share.Title
|
||||
}
|
||||
if d.share.ShareTheme != "" {
|
||||
theme, ok := config.Frontend.Styling.CustomThemeOptions[d.share.ShareTheme]
|
||||
if ok {
|
||||
userSelectedTheme = theme.CssRaw
|
||||
}
|
||||
}
|
||||
if d.share.ShareTheme != "" {
|
||||
theme, ok := config.Frontend.Styling.CustomThemeOptions[d.share.ShareTheme]
|
||||
@@ -176,7 +184,7 @@ func handleWithStaticData(w http.ResponseWriter, r *http.Request, d *requestCont
|
||||
loginIcon := staticURL + "/loginIcon"
|
||||
|
||||
data["htmlVars"] = map[string]interface{}{
|
||||
"title": config.Frontend.Name,
|
||||
"title": title,
|
||||
"customCSS": config.Frontend.Styling.CustomCSSRaw,
|
||||
"userSelectedTheme": userSelectedTheme,
|
||||
"lightBackground": config.Frontend.Styling.LightBackground,
|
||||
@@ -188,7 +196,7 @@ func handleWithStaticData(w http.ResponseWriter, r *http.Request, d *requestCont
|
||||
"color": defaultThemeColor,
|
||||
"winIcon": staticURL + "/img/icons/mstile-144x144.png",
|
||||
"appIcon": staticURL + "/img/icons/android-chrome-256x256.png",
|
||||
"description": config.Frontend.Description,
|
||||
"description": description,
|
||||
}
|
||||
// variables consumed by frontend as json
|
||||
data["globalVars"] = map[string]interface{}{
|
||||
|
||||
@@ -164,7 +164,7 @@ func usersPostHandler(w http.ResponseWriter, r *http.Request, d *requestContext)
|
||||
return http.StatusBadRequest, errors.ErrEmptyPassword
|
||||
}
|
||||
|
||||
err = storage.CreateUser(req.User)
|
||||
err = storage.CreateUser(req.User, req.User.Permissions)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fetchURL, adjustedData } from './utils'
|
||||
import { getApiPath, doubleEncode, getPublicApiPath } from '@/utils/url.js'
|
||||
import { mutations } from '@/store'
|
||||
import { mutations,state } from '@/store'
|
||||
import { notify } from '@/notify'
|
||||
import { globalVars } from '@/utils/constants'
|
||||
|
||||
@@ -101,7 +101,8 @@ export function download(format, files, shareHash = "") {
|
||||
const apiPath = getApiPath(shareHash == "" ? 'api/raw' : 'public/api/raw', {
|
||||
files: fileargs,
|
||||
algo: format,
|
||||
hash: shareHash
|
||||
hash: shareHash,
|
||||
...(state.share.token && { token: state.share.token })
|
||||
})
|
||||
const url = window.origin + apiPath
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ export default {
|
||||
|
||||
// Add keyboard event listener for "/" to activate search
|
||||
this.handleKeydown = (event) => {
|
||||
if (event.key === '/' && !state.isSearchActive) {
|
||||
if (event.key === '/' && !state.isSearchActive && getters.currentPrompt() === null) {
|
||||
event.preventDefault();
|
||||
this.open();
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
</div>
|
||||
|
||||
<div v-if="!shareInfo.disableDownload" class="share__box__element share__box__center">
|
||||
<button class="button button--flat clickable" @click="goToDownload()"> {{ $t("buttons.download") }} </button>
|
||||
<button class="button button--flat clickable" @click="goToDownload()"> {{ $t("buttons.download") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -41,7 +42,7 @@
|
||||
|
||||
<script>
|
||||
import { publicApi } from "@/api";
|
||||
import { state, getters } from "@/store";
|
||||
import { state, getters, mutations } from "@/store";
|
||||
import { getHumanReadableFilesize } from "@/utils/filesizes";
|
||||
import { getTypeInfo } from "@/utils/mimetype";
|
||||
import QrcodeVue from "qrcode.vue";
|
||||
@@ -115,13 +116,29 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
goToDownload() {
|
||||
const downloadLink = publicApi.getDownloadURL({
|
||||
path: "/",
|
||||
hash: state.share.hash,
|
||||
token: state.share.token,
|
||||
inline: false,
|
||||
}, [state.req.path]);
|
||||
window.open(downloadLink, "_blank");
|
||||
if (state.req.items.length > 1) {
|
||||
mutations.showHover({
|
||||
name: "download",
|
||||
confirm: (format) => {
|
||||
mutations.closeHovers();
|
||||
const downloadLink = publicApi.getDownloadURL({
|
||||
path: "/",
|
||||
hash: state.share.hash,
|
||||
token: state.share.token,
|
||||
inline: false,
|
||||
}, [state.req.path]);
|
||||
window.open(downloadLink + "&format=" + format, "_blank");
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const downloadLink = publicApi.getDownloadURL({
|
||||
path: "/",
|
||||
hash: state.share.hash,
|
||||
token: state.share.token,
|
||||
inline: false,
|
||||
}, [state.req.path]);
|
||||
window.open(downloadLink, "_blank");
|
||||
}
|
||||
},
|
||||
getShareLink() {
|
||||
return publicApi.getShareURL({
|
||||
|
||||
@@ -514,9 +514,7 @@ button.action {
|
||||
}
|
||||
|
||||
.headline-card {
|
||||
padding: 1em;
|
||||
overflow: hidden !important;
|
||||
min-height: fit-content;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.person-button {
|
||||
|
||||
@@ -13,13 +13,23 @@ export default function downloadFiles(items) {
|
||||
}
|
||||
if (getters.isShare()) {
|
||||
// Perform download without opening a new window
|
||||
startDownload(null, items, state.share.hash);
|
||||
if (getters.isSingleFileSelected()) {
|
||||
startDownload(null, items, state.share.hash);
|
||||
} else {
|
||||
// Multiple files download with user confirmation
|
||||
mutations.showHover({
|
||||
name: "download",
|
||||
confirm: (format) => {
|
||||
mutations.closeHovers();
|
||||
startDownload(format, items, state.share.hash);
|
||||
},
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (getters.isSingleFileSelected()) {
|
||||
startDownload(null, items);
|
||||
return;
|
||||
} else {
|
||||
// Multiple files download with user confirmation
|
||||
mutations.showHover({
|
||||
|
||||
@@ -967,9 +967,6 @@ export default {
|
||||
mutations.setMultiple(val == true);
|
||||
showMultipleSelection();
|
||||
},
|
||||
openSearch() {
|
||||
this.currentPrompt = "search";
|
||||
},
|
||||
windowsResize: throttle(function () {
|
||||
this.colunmsResize();
|
||||
this.width = window.innerWidth;
|
||||
|
||||
@@ -88,7 +88,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
permissions() {
|
||||
return state.user.permissions;
|
||||
return getters.permissions();
|
||||
},
|
||||
showImage() {
|
||||
if (state.req.type == "image/heic" || state.req.type == "image/heif") {
|
||||
|
||||
Reference in new issue
Block a user