Compare commits

..

10 Commits

Author SHA1 Message Date
Henrique Dias
d1a73a8b18 chore(release): 2.34.2 2025-06-29 16:12:09 +02:00
Henrique Dias
2b5d6cbb99 fix: mitigate unprotected shares 2025-06-29 16:06:20 +02:00
Henrique Dias
364f391017 docs: cleanup installation 2025-06-29 15:53:02 +02:00
Henrique Dias
c13861e13c docs: clarify admin password 2025-06-29 15:36:58 +02:00
Henrique Dias
e6b750add5 chore: make more fields in bug report mandatory 2025-06-29 15:06:18 +02:00
Henrique Dias
70d59ec03e chore(release): 2.34.1 2025-06-29 11:28:57 +02:00
Henrique Dias
bf37f88c32 fix: passthrough the minimum password length (#5236) 2025-06-29 11:28:32 +02:00
Foxy Hunter
7354eb6cf9 fix: exclude to-be-moved folder from move dialog (#5235) 2025-06-29 11:23:06 +02:00
Henrique Dias
10684e5390 docs: bring the maintenance warning higher in the page 2025-06-29 10:13:39 +02:00
Henrique Dias
58fe817349 docs: add link to contributing and license in readme 2025-06-29 10:13:01 +02:00
21 changed files with 100172 additions and 104 deletions

View File

@@ -20,22 +20,32 @@ body:
render: Text
description: |
Enter the version of FileBrowser you are using.
validations:
required: true
- type: textarea
attributes:
label: Description
description: |
A clear and concise description of what the issue is about. What are you trying to do?
validations:
required: true
- type: textarea
attributes:
label: What did you expect to happen?
validations:
required: true
- type: textarea
attributes:
label: What actually happened?
validations:
required: true
- type: textarea
attributes:
label: Reproduction Steps
description: |
Tell us how to reproduce this issue. How can someone who is starting from scratch reproduce this behavior as minimally as possible?
validations:
required: true
- type: textarea
attributes:
label: Files

View File

@@ -2,6 +2,21 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [2.34.2](https://github.com/filebrowser/filebrowser/compare/v2.34.1...v2.34.2) (2025-06-29)
### Bug Fixes
* mitigate unprotected shares ([2b5d6cb](https://github.com/filebrowser/filebrowser/commit/2b5d6cbb996a61a769acc56af0acc12eec2d8d8f))
### [2.34.1](https://github.com/filebrowser/filebrowser/compare/v2.34.0...v2.34.1) (2025-06-29)
### Bug Fixes
* exclude to-be-moved folder from move dialog ([#5235](https://github.com/filebrowser/filebrowser/issues/5235)) ([7354eb6](https://github.com/filebrowser/filebrowser/commit/7354eb6cf966244141277c2808988855c004f908))
* passthrough the minimum password length ([#5236](https://github.com/filebrowser/filebrowser/issues/5236)) ([bf37f88](https://github.com/filebrowser/filebrowser/commit/bf37f88c32222ad9c186482bb97338a9c9b4a93c))
## [2.34.0](https://github.com/filebrowser/filebrowser/compare/v2.33.10...v2.34.0) (2025-06-29)

View File

@@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2018 File Browser contributors
Copyright 2018 File Browser Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -28,3 +28,11 @@ Documentation on how to install, configure, and contribute to this project is ho
[issues]: https://github.com/filebrowser/filebrowser/issues
[discussions]: https://github.com/filebrowser/filebrowser/discussions
## Contributing
Contributions are always welcome. To start contributing to this project, read our [guidelines](CONTRIBUTING.md) first.
## License
[Apache License 2.0](LICENSE) © File Browser Contributors

View File

@@ -150,7 +150,7 @@ func (a *HookAuth) SaveUser() (*users.User, error) {
}
if u == nil {
pass, err := users.HashAndValidatePwd(a.Cred.Password, a.Settings.MinimumPasswordLength)
pass, err := users.ValidateAndHashPwd(a.Cred.Password, a.Settings.MinimumPasswordLength)
if err != nil {
return nil, err
}
@@ -186,7 +186,7 @@ func (a *HookAuth) SaveUser() (*users.User, error) {
// update the password when it doesn't match the current
if p {
pass, err := users.HashAndValidatePwd(a.Cred.Password, a.Settings.MinimumPasswordLength)
pass, err := users.ValidateAndHashPwd(a.Cred.Password, a.Settings.MinimumPasswordLength)
if err != nil {
return nil, err
}

View File

@@ -35,7 +35,7 @@ func (a ProxyAuth) createUser(usr users.Store, setting *settings.Settings, srv *
}
var hashedRandomPassword string
hashedRandomPassword, err = users.HashAndValidatePwd(pwd, setting.MinimumPasswordLength)
hashedRandomPassword, err = users.ValidateAndHashPwd(pwd, setting.MinimumPasswordLength)
if err != nil {
return nil, err
}

View File

@@ -432,7 +432,7 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) {
log.Println("Randomly generated password for user 'admin':", pwd)
password, err = users.HashAndValidatePwd(pwd, set.MinimumPasswordLength)
password, err = users.ValidateAndHashPwd(pwd, set.MinimumPasswordLength)
checkErr(err)
}

View File

@@ -21,7 +21,7 @@ var usersAddCmd = &cobra.Command{
checkErr(err)
getUserDefaults(cmd.Flags(), &s.Defaults, false)
password, err := users.HashAndValidatePwd(args[1], s.MinimumPasswordLength)
password, err := users.ValidateAndHashPwd(args[1], s.MinimumPasswordLength)
checkErr(err)
user := &users.User{

View File

@@ -66,7 +66,7 @@ options you want to change.`,
}
if password != "" {
user.Password, err = users.HashAndValidatePwd(password, s.MinimumPasswordLength)
user.Password, err = users.ValidateAndHashPwd(password, s.MinimumPasswordLength)
checkErr(err)
}

View File

@@ -1,13 +1,16 @@
package errors
import "errors"
import (
"errors"
"fmt"
)
var (
ErrEmptyKey = errors.New("empty key")
ErrExist = errors.New("the resource already exists")
ErrNotExist = errors.New("the resource does not exist")
ErrEmptyPassword = errors.New("password is empty")
ErrShortPassword = errors.New("password is too short")
ErrEasyPassword = errors.New("password is too easy")
ErrEmptyUsername = errors.New("username is empty")
ErrEmptyRequest = errors.New("empty request")
ErrScopeIsRelative = errors.New("scope is a relative path")
@@ -20,3 +23,11 @@ var (
ErrSourceIsParent = errors.New("source is parent")
ErrRootUserDeletion = errors.New("user with id 1 can't be deleted")
)
type ErrShortPassword struct {
MinimumLength uint
}
func (e ErrShortPassword) Error() string {
return fmt.Sprintf("password is too short, minimum length is %d", e.MinimumLength)
}

View File

@@ -35,6 +35,12 @@ import { StatusError } from "@/api/utils.js";
export default {
name: "file-list",
props: {
exclude: {
type: Array,
default: () => [],
},
},
data: function () {
return {
items: [],
@@ -90,6 +96,7 @@ export default {
// move options.
for (const item of req.items) {
if (!item.isDir) continue;
if (this.exclude?.includes(item.url)) continue;
this.items.push({
name: item.name,

View File

@@ -8,6 +8,7 @@
<file-list
ref="fileList"
@update:selected="(val) => (dest = val)"
:exclude="excludedFolders"
tabindex="1"
/>
</div>
@@ -76,6 +77,11 @@ export default {
computed: {
...mapState(useFileStore, ["req", "selected"]),
...mapState(useAuthStore, ["user"]),
excludedFolders() {
return this.selected
.filter((idx) => this.req.items[idx].isDir)
.map((idx) => this.req.items[idx].url);
},
},
methods: {
...mapActions(useLayoutStore, ["showHover", "closeHovers"]),

View File

@@ -32,16 +32,6 @@
<i class="material-icons">content_paste</i>
</button>
</td>
<td class="small" v-if="hasDownloadLink()">
<button
class="action copy-clipboard"
:aria-label="$t('buttons.copyDownloadLinkToClipboard')"
:title="$t('buttons.copyDownloadLinkToClipboard')"
@click="copyToClipboard(buildDownloadLink(link))"
>
<i class="material-icons">content_paste_go</i>
</button>
</td>
<td class="small">
<button
class="action"
@@ -142,7 +132,7 @@
<script>
import { mapActions, mapState } from "pinia";
import { useFileStore } from "@/stores/file";
import { share as api, pub as pub_api } from "@/api";
import { share as api } from "@/api";
import dayjs from "dayjs";
import { useLayoutStore } from "@/stores/layout";
import { copy } from "@/utils/clipboard";
@@ -257,14 +247,6 @@ export default {
buildLink(share) {
return api.getShareURL(share);
},
hasDownloadLink() {
return (
this.selected.length === 1 && !this.req.items[this.selected[0]].isDir
);
},
buildDownloadLink(share) {
return pub_api.getDownloadURL(share);
},
sort() {
this.links = this.links.sort((a, b) => {
if (a.expire === 0) return -1;

View File

@@ -151,9 +151,9 @@ var signupHandler = func(_ http.ResponseWriter, r *http.Request, d *data) (int,
d.settings.Defaults.Apply(user)
pwd, err := users.HashAndValidatePwd(info.Password, d.settings.MinimumPasswordLength)
pwd, err := users.ValidateAndHashPwd(info.Password, d.settings.MinimumPasswordLength)
if err != nil {
return http.StatusInternalServerError, err
return http.StatusBadRequest, err
}
user.Password = pwd

View File

@@ -125,13 +125,9 @@ var userPostHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *
return http.StatusBadRequest, fbErrors.ErrEmptyPassword
}
if len(req.Data.Password) < int(d.settings.MinimumPasswordLength) {
return http.StatusBadRequest, fbErrors.ErrShortPassword
}
req.Data.Password, err = users.HashAndValidatePwd(req.Data.Password, d.settings.MinimumPasswordLength)
req.Data.Password, err = users.ValidateAndHashPwd(req.Data.Password, d.settings.MinimumPasswordLength)
if err != nil {
return http.StatusInternalServerError, err
return http.StatusBadRequest, err
}
userHome, err := d.settings.MakeUserDir(req.Data.Username, req.Data.Scope, d.server.Root)
@@ -167,17 +163,19 @@ var userPutHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request
}
if req.Data.Password != "" {
req.Data.Password, err = users.HashAndValidatePwd(req.Data.Password, d.settings.MinimumPasswordLength)
req.Data.Password, err = users.ValidateAndHashPwd(req.Data.Password, d.settings.MinimumPasswordLength)
if err != nil {
return http.StatusBadRequest, err
}
} else {
var suser *users.User
suser, err = d.store.Users.Get(d.server.Root, d.raw.(uint))
if err != nil {
return http.StatusInternalServerError, err
}
req.Data.Password = suser.Password
}
if err != nil {
return http.StatusInternalServerError, err
}
req.Which = []string{}
}
@@ -190,13 +188,9 @@ var userPutHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request
return http.StatusForbidden, nil
}
if len(req.Data.Password) < int(d.settings.MinimumPasswordLength) {
return http.StatusBadRequest, fbErrors.ErrShortPassword
}
req.Data.Password, err = users.HashAndValidatePwd(req.Data.Password, d.settings.MinimumPasswordLength)
req.Data.Password, err = users.ValidateAndHashPwd(req.Data.Password, d.settings.MinimumPasswordLength)
if err != nil {
return http.StatusInternalServerError, err
return http.StatusBadRequest, err
}
}

26
users/assets.go Normal file
View File

@@ -0,0 +1,26 @@
package users
import (
"embed"
"strings"
)
//go:embed assets
var assets embed.FS
var commonPasswords map[string]struct{}
//nolint:gochecknoinits
func init() {
// Password list sourced from:
// https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/100k-most-used-passwords-NCSC.txt
data, err := assets.ReadFile("assets/common-passwords.txt")
if err != nil {
panic(err)
}
passwords := strings.Split(strings.TrimSpace(string(data)), "\n")
commonPasswords = make(map[string]struct{}, len(passwords))
for _, password := range passwords {
commonPasswords[strings.TrimSpace(password)] = struct{}{}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -9,10 +9,14 @@ import (
fbErrors "github.com/filebrowser/filebrowser/v2/errors"
)
// HashPwd hashes a password.
func HashAndValidatePwd(password string, minimumLength uint) (string, error) {
// ValidateAndHashPwd validates and hashes a password.
func ValidateAndHashPwd(password string, minimumLength uint) (string, error) {
if uint(len(password)) < minimumLength {
return "", fbErrors.ErrShortPassword
return "", fbErrors.ErrShortPassword{MinimumLength: minimumLength}
}
if _, ok := commonPasswords[password]; ok {
return "", fbErrors.ErrEasyPassword
}
return HashPwd(password)

View File

@@ -8,12 +8,12 @@
<img src="https://raw.githubusercontent.com/filebrowser/logo/master/banner.png" width="550"/>
</p>
![Preview](static/example.gif)
> [!WARNING]
>
> This project is currently on **maintenance-only** mode. For more information, read the information on [GitHub](https://github.com/filebrowser/filebrowser#project-status).
![Preview](static/example.gif)
File Browser provides a file managing interface within a specified directory and it can be used to upload, delete, preview and edit your files. It is a **create-your-own-cloud**-kind of software where you can just install it on your server, direct it to a path and access your files through a nice web interface.
## Features

View File

@@ -1,75 +1,68 @@
# Installation
File Browser is a single binary and can be used as a standalone executable. Although, some might prefer to use it with [Docker](https://www.docker.com) or [Caddy](https://caddyserver.com), which is a fantastic web server that enables HTTPS by default. Its installation is quite straightforward independently on which system you want to use.
File Browser is a single binary and can be used as standalone executable. However, it is also available as a [Docker](https://www.docker.com) image. The installation and first time setup is quite straightforward independently of which system you use.
## Quick Setup
## Binary
The quickest way for beginners to start using File Browser is by opening your terminal and executing the following commands:
The quickest and easiest way to install File Browser is to use a package manager, or our download script, which automatically fetches the latest version of File Browser for your platform.
### Brew
=== "Brew"
```sh
brew tap filebrowser/tap
brew install filebrowser
filebrowser -r /path/to/your/files
```
```sh
brew tap filebrowser/tap
brew install filebrowser
filebrowser -r /path/to/your/files
```
### Unix
=== "Unix"
```sh
curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash
filebrowser -r /path/to/your/files
```
```sh
curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash
filebrowser -r /path/to/your/files
```
### Windows
=== "Windows"
```sh
iwr -useb https://raw.githubusercontent.com/filebrowser/get/master/get.ps1 | iex
filebrowser -r /path/to/your/files
```
```sh
iwr -useb https://raw.githubusercontent.com/filebrowser/get/master/get.ps1 | iex
filebrowser -r /path/to/your/files
```
### Configuring
Done! It will bootstrap a database in which all the configurations and users are stored. Now, you can see on your command line the address in which your instance is running. You just need to go to that URL and use the following credentials:
* Username: `admin`
* Password: (printed in your console)
Although this is the fastest way to bootstrap an instance, we recommend you to take a look at other possible options, by checking `config init --help` and `config set --help`, to make the installation as safe and customized as it can be.
File Browser is now up and running. Read some [first boot](#first-boot) for more information.
## Docker
File Browser is available as two different Docker images, which can be found on [Docker Hub](https://hub.docker.com/r/filebrowser/filebrowser).
### Alpine
=== "Alpine"
```sh
docker run \
-v /path/to/srv:/srv \
-v /path/to/database:/database \
-v /path/to/config:/config \
-p 8080:80 \
filebrowser/filebrowser
```
The
The default user has PID 1000 and GID 1000. Please make sure that this user has access to the different mounted volumes. To change the user running inside the Docker image, you need to use the [`--user` flag](https://docs.docker.com/engine/containers/run/#user).
```sh
docker run \
-v /path/to/srv:/srv \
-v /path/to/database:/database \
-v /path/to/config:/config \
-p 8080:80 \
filebrowser/filebrowser
```
### s6 overlay
The default user has PID 1000 and GID 1000. Please make sure that this user has access to the different mounted volumes. To change the user running inside the Docker image, you need to use the [`--user` flag](https://docs.docker.com/engine/containers/run/#user).
The `s6` image is based on LinuxServer and leverages the [s6-overlay](https://github.com/just-containers/s6-overlay) system for a standard, highly customizable image. It should be used as follows:
=== "s6 overlay"
```shell
docker run \
-v /path/to/srv:/srv \
-v /path/to/database:/database \
-v /path/to/config:/config \
-e PUID=$(id -u) \
-e PGID=$(id -g) \
-p 8080:80 \
filebrowser/filebrowser:s6
```
The `s6` image is based on LinuxServer and leverages the [s6-overlay](https://github.com/just-containers/s6-overlay) system for a standard, highly customizable image. It should be used as follows:
### Notes
```shell
docker run \
-v /path/to/srv:/srv \
-v /path/to/database:/database \
-v /path/to/config:/config \
-e PUID=$(id -u) \
-e PGID=$(id -g) \
-p 8080:80 \
filebrowser/filebrowser:s6
```
Where:
@@ -78,3 +71,15 @@ Where:
- `/path/to/database` contains a `filebrowser.db` file
Both `settings.json` and `filebrowser.db` will automatically be initialized if they don't exist.
File Browser is now up and running. Read some [first boot](#first-boot) for more information.
## First Boot
Your instance is now up and running. File Browser will automatically bootstrap a database, in which the configuration and the users are stored. You can find the address in which your instance is running, as well as the randomly generated password for the user `admin`, in the console logs.
Although this is the fastest way to bootstrap an instance, we recommend you to take a look at other possible options, by checking `config init --help` and `config set --help`, to make the installation as safe and customized as it can be.
> [!WARNING]
>
> The automatically generated password for the user `admin` is only displayed once. If you fail to remember it, you will need to manually delete the database and start File Browser again.

View File

@@ -1,12 +1,12 @@
site_name: File Browser
site_description: 'A web-based file browser and manager for your files'
site_author: 'File Browser Community'
site_author: 'File Browser Contributors'
site_url: 'https://filebrowser.org'
repo_name: 'filebrowser/filebrowser'
repo_url: 'https://github.com/filebrowser/filebrowser'
copyright: 'Copyright &copy; 2025 File Browser Community'
copyright: 'Copyright &copy; 2025 File Browser Contributors'
theme:
name: material