mirror of
https://github.com/Forceu/Gokapi.git
synced 2025-12-21 08:59:50 -06:00
Add deprecation alerts, deprecate DOCKER_NONROOT in favor of docker --user ... (#327)
* deprecate DOCKER_NONROOT in favor of docker --user ... * remove redundant named volumes creation in compose * remove DOCKER_NONROOT from demo env file * add deprecation warning to docker entrypoint * update documentation * Added feature to show deprecation messages in UI and logs Added deprecation message for Docker_NONROOT Fixed documentation --------- Co-authored-by: Marc Ole Bulling <Marc-Ole@gmx.de>
This commit is contained in:
@@ -33,4 +33,3 @@ TZ=UTC
|
||||
#GOKAPI_DISABLE_CORS_CHECK=false
|
||||
#GOKAPI_LOG_STDOUT=false
|
||||
#GOKAPI_ENABLE_HOTLINK_VIDEOS=false
|
||||
#DOCKER_NONROOT=false
|
||||
|
||||
@@ -137,6 +137,6 @@ func fileExists(filename string) bool {
|
||||
// Auto-generated content below, do not modify
|
||||
// Version codes can be changed in updateVersionNumbers.go
|
||||
|
||||
const jsAdminVersion = 12
|
||||
const jsAdminVersion = 13
|
||||
const jsE2EVersion = 8
|
||||
const cssMainVersion = 5
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const versionJsAdmin = 12
|
||||
const versionJsAdmin = 13
|
||||
const versionJsDropzone = 5
|
||||
const versionJsE2EAdmin = 8
|
||||
const versionCssMain = 5
|
||||
|
||||
@@ -67,6 +67,7 @@ func main() {
|
||||
initCloudConfig(passedFlags)
|
||||
go storage.CleanUp(true)
|
||||
logging.LogStartup()
|
||||
showDeprecationWarnings()
|
||||
go webserver.Start()
|
||||
|
||||
c := make(chan os.Signal)
|
||||
@@ -107,6 +108,17 @@ func showVersion(passedFlags flagparser.MainFlags) {
|
||||
osExit(0)
|
||||
}
|
||||
|
||||
func showDeprecationWarnings() {
|
||||
for _, dep := range configuration.Environment.ActiveDeprecations {
|
||||
fmt.Println()
|
||||
fmt.Println("WARNING, deprecated feature: " + dep.Name)
|
||||
fmt.Println(dep.Description)
|
||||
fmt.Println("See " + dep.DocUrl + " for more information.")
|
||||
fmt.Println()
|
||||
logging.LogDeprecation(dep)
|
||||
}
|
||||
}
|
||||
|
||||
func parseBuildSettings(infos []debug.BuildSetting) {
|
||||
lookups := make(map[string]string)
|
||||
lookups["-tags"] = "Build Tags"
|
||||
|
||||
@@ -11,8 +11,3 @@ services:
|
||||
restart: always
|
||||
env_file:
|
||||
- "./.env"
|
||||
|
||||
volumes:
|
||||
gokapi-data:
|
||||
gokapi-config:
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#!/bin/sh
|
||||
#DEPRECATED, see https://gokapi.readthedocs.io/en/latest/setup.html#migration-from-docker-nonroot-to-docker-user
|
||||
if [ "$DOCKER_NONROOT" = "true" ]; then
|
||||
# TODO for the next major upgrade version:
|
||||
# - Remove this code block and leave only exec /app/gokapi "@"
|
||||
# - Remove gokapi user / group creation in Dockerfile
|
||||
# - Remove su-exec installation from the Dockerfile
|
||||
echo "Setting permissions" && \
|
||||
chown -R gokapi:gokapi /app && \
|
||||
chmod -R 700 /app && \
|
||||
|
||||
@@ -94,7 +94,9 @@ Available environment variables
|
||||
| | | | |
|
||||
| | unlimited downloads enabled | | |
|
||||
+-------------------------------+-------------------------------------------------------------------------------------+-----------------+--------------------------------------+
|
||||
| DOCKER_NONROOT | Docker only: Runs the binary in the container as a non-root user, if set to "true" | No | false |
|
||||
| DOCKER_NONROOT | DEPRECATED. See :ref:`setupdocker` section for non-root setup | No | false |
|
||||
| | | | |
|
||||
| | Docker only: Runs the binary in the container as a non-root user, if set to "true" | | |
|
||||
+-------------------------------+-------------------------------------------------------------------------------------+-----------------+--------------------------------------+
|
||||
| TMPDIR | Sets the path which contains temporary files | No | Non-Docker: Default OS path |
|
||||
| | | | |
|
||||
|
||||
@@ -66,6 +66,8 @@ Starting Gokapi
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
.. _setupdocker:
|
||||
|
||||
Docker
|
||||
""""""""""
|
||||
|
||||
@@ -77,10 +79,45 @@ With the argument ``-p 127.0.0.1:53842:53842`` the service will only be accessib
|
||||
|
||||
Set ``-e TZ=UTC`` to the timezone you are in, e.g. ``-e TZ=Europe/Berlin``.
|
||||
|
||||
If you do not want the binary to run as the root user in the container, you can set the environment variable ``DOCKER_NONROOT`` to true.
|
||||
|
||||
Please make sure that ``/app/data`` and ``/app/config`` are mounted as volumes (see example above), otherwise you will lose all your data after rebuilding or updating your container.
|
||||
|
||||
If you do not want the binary to run as the root user in the container, you can run it with ``--user`` option, like in the following example: ::
|
||||
|
||||
docker run --user "1000:1000" -v ./gokapi-data:/app/data -v ./gokapi-config:/app/config -p 127.0.0.1:53842:53842 -e TZ=UTC f0rc3/gokapi:latest
|
||||
|
||||
Where ``1000:1000`` are colon separated desired user ID and group ID. Please note the command uses bind mounts instead of named volumes. Make sure that the user has read / write permissions to the volumes directories. You can change the names of ``./gokapi-data`` and ``./gokapi-config`` directories to your liking.
|
||||
|
||||
|
||||
.. _deprecation_nonroot:
|
||||
|
||||
Migration from DOCKER_NONROOT to docker --user
|
||||
***********************************************
|
||||
|
||||
With deprecation of ``DOCKER_NONROOT`` environment variable you may want to consider migration of your existing configuration and data to ``docker --user`` option approach. The steps are as follows:
|
||||
|
||||
::
|
||||
|
||||
# Copy configuration and data from the container to your docker host machine.
|
||||
# Make sure ./gokapi-config and ./gokapi-data directories are not present before
|
||||
# the following commands are executed
|
||||
docker cp gokapi:/app/config ./gokapi-config
|
||||
docker cp gokapi:/app/data ./gokapi-data
|
||||
|
||||
# Remove the current container
|
||||
docker rm -f gokapi
|
||||
|
||||
# Start a new container with the current linux session user
|
||||
docker run --user "$(id -u):$(id -g)" -v ./gokapi-data:/app/data -v ./gokapi-config:/app/config -p 127.0.0.1:53842:53842 -e TZ=UTC f0rc3/gokapi:latest
|
||||
|
||||
Where:
|
||||
* ``gokapi`` is the container name. For you it can be different.
|
||||
* ``/app/config`` and ``/app/data`` are directories inside container where configuration and data reside. Can be different, depending on your ``GOKAPI_CONFIG_DIR`` and ``GOKAPI_DATA_DIR`` settings.
|
||||
|
||||
This example uses your current user ID and group ID for starting the container. To use a different IDs, replace ``$(id -u)`` with the actual user ID and ``$(id -g)`` with the actual group ID.
|
||||
|
||||
|
||||
|
||||
|
||||
Docker Compose
|
||||
""""""""""""""""
|
||||
|
||||
@@ -92,6 +129,8 @@ By default, the container is set to always automatically (re)start when the syst
|
||||
|
||||
Then, start the container with the command ``docker compose up -d``
|
||||
|
||||
|
||||
|
||||
Native Deployment
|
||||
""""""""""""""""""
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"path"
|
||||
|
||||
envParser "github.com/caarlos0/env/v6"
|
||||
"github.com/forceu/gokapi/internal/environment/deprecation"
|
||||
"github.com/forceu/gokapi/internal/environment/flagparser"
|
||||
"github.com/forceu/gokapi/internal/helper"
|
||||
)
|
||||
@@ -35,11 +36,21 @@ type Environment struct {
|
||||
AwsKeyId string `env:"AWS_KEY"`
|
||||
AwsKeySecret string `env:"AWS_KEY_SECRET"`
|
||||
AwsEndpoint string `env:"AWS_ENDPOINT"`
|
||||
ActiveDeprecations []deprecation.Deprecation
|
||||
}
|
||||
|
||||
// New parses the env variables
|
||||
func New() Environment {
|
||||
result := Environment{WebserverPort: DefaultPort}
|
||||
|
||||
result = parseEnvVars(result)
|
||||
result = parseFlags(result)
|
||||
result.ActiveDeprecations = deprecation.GetActive()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func parseEnvVars(result Environment) Environment {
|
||||
err := envParser.Parse(&result, envParser.Options{
|
||||
Prefix: "GOKAPI_",
|
||||
})
|
||||
@@ -50,6 +61,23 @@ func New() Environment {
|
||||
}
|
||||
helper.Check(err)
|
||||
|
||||
if result.LengthId < 5 {
|
||||
result.LengthId = 5
|
||||
}
|
||||
if result.LengthHotlinkId < 8 {
|
||||
result.LengthHotlinkId = 8
|
||||
}
|
||||
if result.MaxMemory < 5 {
|
||||
result.MaxMemory = 5
|
||||
}
|
||||
if result.MaxFileSize < 1 {
|
||||
result.MaxFileSize = 5
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func parseFlags(result Environment) Environment {
|
||||
flags := flagparser.ParseFlags()
|
||||
if flags.IsPortSet {
|
||||
result.WebserverPort = flags.Port
|
||||
@@ -67,8 +95,9 @@ func New() Environment {
|
||||
if flags.IsConfigPathSet {
|
||||
result.ConfigPath = flags.ConfigPath
|
||||
}
|
||||
|
||||
if IsDockerInstance() && os.Getenv("TMPDIR") == "" {
|
||||
err = os.Setenv("TMPDIR", result.DataDir)
|
||||
err := os.Setenv("TMPDIR", result.DataDir)
|
||||
helper.Check(err)
|
||||
}
|
||||
if result.LengthId < 5 {
|
||||
|
||||
49
internal/environment/deprecation/Deprecations.go
Normal file
49
internal/environment/deprecation/Deprecations.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package deprecation
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Deprecation struct {
|
||||
Id string
|
||||
Name string
|
||||
Description string
|
||||
DocUrl string
|
||||
checkFunction func() bool
|
||||
}
|
||||
|
||||
func (d *Deprecation) IsSet() bool {
|
||||
if d.checkFunction == nil {
|
||||
panic("checkFunction is nil")
|
||||
}
|
||||
return d.checkFunction()
|
||||
}
|
||||
|
||||
func GetActive() []Deprecation {
|
||||
result := make([]Deprecation, 0)
|
||||
for _, deprecation := range availableDeprecations {
|
||||
if deprecation.IsSet() {
|
||||
result = append(result, deprecation)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var availableDeprecations = []Deprecation{
|
||||
{
|
||||
Id: "dockernonroot",
|
||||
Name: "Docker Non-Root User",
|
||||
Description: "Usage of DOCKER_NONROOT is deprecated in favor of docker --user option",
|
||||
DocUrl: "https://gokapi.readthedocs.io/en/latest/setup.html#migration-from-docker-nonroot-to-docker-user",
|
||||
checkFunction: isNonRootSet,
|
||||
},
|
||||
}
|
||||
|
||||
func isNonRootSet() bool {
|
||||
envVal := os.Getenv("DOCKER_NONROOT")
|
||||
if envVal == "" || strings.ToLower(envVal) == "false" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/forceu/gokapi/internal/environment"
|
||||
"github.com/forceu/gokapi/internal/environment/deprecation"
|
||||
"github.com/forceu/gokapi/internal/helper"
|
||||
"github.com/forceu/gokapi/internal/models"
|
||||
)
|
||||
@@ -139,6 +140,13 @@ func LogRestore(file models.File, user models.User) {
|
||||
createLogEntry(categoryEdit, fmt.Sprintf("%s, ID %s, restored by %s (user #%d)", file.Name, file.Id, user.Name, user.Id), false)
|
||||
}
|
||||
|
||||
// LogDeprecation adds a log entry to indicate that a deprecated feature is being used. Blocking
|
||||
func LogDeprecation(dep deprecation.Deprecation) {
|
||||
createLogEntry(categoryWarning, "Deprecated feature: "+dep.Name, true)
|
||||
createLogEntry(categoryWarning, dep.Description, true)
|
||||
createLogEntry(categoryWarning, "See "+dep.DocUrl+" for more information.", true)
|
||||
}
|
||||
|
||||
// DeleteLogs removes all logs before the cutoff timestamp and inserts a new log that the user
|
||||
// deleted the previous logs
|
||||
func DeleteLogs(userName string, userId int, cutoff int64, r *http.Request) {
|
||||
|
||||
@@ -581,14 +581,23 @@ func showAdminMenu(w http.ResponseWriter, r *http.Request) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if configuration.Get().Encryption.Level == encryption.EndToEndEncryption {
|
||||
config := configuration.Get()
|
||||
if config.Encryption.Level == encryption.EndToEndEncryption {
|
||||
e2einfo := database.GetEnd2EndInfo(user.Id)
|
||||
if !e2einfo.HasBeenSetUp() {
|
||||
redirect(w, "e2eSetup")
|
||||
return
|
||||
}
|
||||
}
|
||||
err = templateFolder.ExecuteTemplate(w, "admin", (&AdminView{}).convertGlobalConfig(ViewMain, user))
|
||||
|
||||
view := (&AdminView{}).convertGlobalConfig(ViewMain, user)
|
||||
if len(configuration.Environment.ActiveDeprecations) > 0 {
|
||||
if user.UserLevel == models.UserLevelSuperAdmin {
|
||||
view.ShowDeprecationNotice = true
|
||||
}
|
||||
}
|
||||
|
||||
err = templateFolder.ExecuteTemplate(w, "admin", view)
|
||||
helper.CheckIgnoreTimeout(err)
|
||||
}
|
||||
|
||||
@@ -656,30 +665,31 @@ type e2ESetupView struct {
|
||||
|
||||
// AdminView contains parameters for all admin related pages
|
||||
type AdminView struct {
|
||||
Items []models.FileApiOutput
|
||||
ApiKeys []models.ApiKey
|
||||
Users []userInfo
|
||||
ActiveUser models.User
|
||||
UserMap map[int]*models.User
|
||||
ServerUrl string
|
||||
Logs string
|
||||
PublicName string
|
||||
SystemKey string
|
||||
IsAdminView bool
|
||||
IsDownloadView bool
|
||||
IsApiView bool
|
||||
IsLogoutAvailable bool
|
||||
IsUserTabAvailable bool
|
||||
EndToEndEncryption bool
|
||||
IncludeFilename bool
|
||||
IsInternalAuth bool
|
||||
MaxFileSize int
|
||||
ActiveView int
|
||||
ChunkSize int
|
||||
MaxParallelUploads int
|
||||
MinLengthPassword int
|
||||
TimeNow int64
|
||||
CustomContent customStatic
|
||||
Items []models.FileApiOutput
|
||||
ApiKeys []models.ApiKey
|
||||
Users []userInfo
|
||||
ActiveUser models.User
|
||||
UserMap map[int]*models.User
|
||||
ServerUrl string
|
||||
Logs string
|
||||
PublicName string
|
||||
SystemKey string
|
||||
IsAdminView bool
|
||||
IsDownloadView bool
|
||||
IsApiView bool
|
||||
IsLogoutAvailable bool
|
||||
IsUserTabAvailable bool
|
||||
EndToEndEncryption bool
|
||||
IncludeFilename bool
|
||||
IsInternalAuth bool
|
||||
ShowDeprecationNotice bool
|
||||
MaxFileSize int
|
||||
ActiveView int
|
||||
ChunkSize int
|
||||
MaxParallelUploads int
|
||||
MinLengthPassword int
|
||||
TimeNow int64
|
||||
CustomContent customStatic
|
||||
}
|
||||
|
||||
// getUserMap needs to return the map with pointers, otherwise template cannot call
|
||||
|
||||
@@ -174,6 +174,10 @@ a:hover {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.toastdeprecation {
|
||||
background-color: #8b0000;
|
||||
}
|
||||
|
||||
.toastnotification.show {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
|
||||
@@ -1 +1 @@
|
||||
.btn-secondary,.btn-secondary:hover,.btn-secondary:focus{color:#333;text-shadow:none}body{background:url(../../assets/background.jpg)no-repeat 50% fixed;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-pack:center;-webkit-box-pack:center;justify-content:center}td{vertical-align:middle;position:relative}a{color:inherit}a:hover{color:inherit;filter:brightness(80%)}.dropzone{background:#2f343a!important;color:#fff;border-radius:5px}.dropzone:hover{background:#33393f!important;color:#fff;border-radius:5px}.card{margin:0 auto;float:none;margin-bottom:10px;border:2px solid #33393f}.card-body{background-color:#212529;color:#ddd}.card-title{font-weight:900}.admin-input{text-align:center}.form-control:disabled{background:#bababa}.break{flex-basis:100%;height:0}.bd-placeholder-img{font-size:1.125rem;text-anchor:middle;-webkit-user-select:none;-moz-user-select:none;user-select:none}@media(min-width:768px){.bd-placeholder-img-lg{font-size:3.5rem}.break{flex-basis:0}}.masthead{margin-bottom:2rem}.masthead-brand{margin-bottom:0}.nav-masthead .nav-link{padding:.25rem 0;font-weight:700;color:rgba(255,255,255,.5);background-color:transparent;border-bottom:.25rem solid transparent}.nav-masthead .nav-link:hover,.nav-masthead .nav-link:focus{border-bottom-color:rgba(255,255,255,.25)}.nav-masthead .nav-link+.nav-link{margin-left:1rem}.nav-masthead .active{color:#fff;border-bottom-color:#fff}#qroverlay{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.3)}#qrcode{position:absolute;top:50%;left:50%;margin-top:-105px;margin-left:-105px;width:210px;height:210px;border:5px solid #fff}.toastnotification{pointer-events:none;position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background-color:#333;color:#fff;padding:15px;border-radius:5px;box-shadow:0 2px 5px rgba(0,0,0,.3);opacity:0;transition:opacity .3s ease-in-out;z-index:9999}.toastnotification.show{opacity:1;pointer-events:auto}.toast-undo{margin-left:20px;color:#4fc3f7;cursor:pointer;text-decoration:underline;font-weight:700;pointer-events:auto}.toast-undo:hover{color:#81d4fa}.toastnotification:not(.show){pointer-events:none!important}.toastnotification:not(.show) .toast-undo{pointer-events:none}.perm-granted{cursor:pointer;color:#0edf00}.perm-notgranted{cursor:pointer;color:#9f9999}.perm-unavailable{color:#525252}.perm-processing{pointer-events:none;color:#e5eb00}.perm-nochange{cursor:default}.prevent-select{-webkit-user-select:none;-ms-user-select:none;user-select:none}.gokapi-dialog{background-color:#212529;color:#ddd}@keyframes subtleHighlight{0%{background-color:#444950}100%{background-color:transparent}}@keyframes subtleHighlightNewJson{0%{background-color:green}100%{background-color:transparent}}.updatedDownloadCount{animation:subtleHighlight .5s ease-out}.newApiKey{animation:subtleHighlightNewJson .7s ease-out}.newUser{animation:subtleHighlightNewJson .7s ease-out}.newItem{animation:subtleHighlightNewJson 1.5s ease-out}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.rowDeleting{animation:fadeOut .3s ease-out forwards}.highlighted-password{background-color:#444;color:#ddd;padding:2px 6px;border-radius:4px;font-weight:700;font-family:monospace;display:inline-block;margin-left:8px;border:1px solid #555}.filename{font-weight:700;font-size:14px;margin-bottom:5px}.upload-progress-container{display:flex;align-items:center}.upload-progress-bar{position:relative;height:10px;background-color:#eee;flex:1;margin-right:10px;border-radius:4px}.upload-progress-bar-progress{position:absolute;top:0;left:0;height:100%;background-color:#0a0;border-radius:4px;transition:width .2s ease-in-out}.upload-progress-info{font-size:12px}.us-container{margin-top:10px;margin-bottom:20px}.uploaderror{font-weight:700;color:red;margin-bottom:5px}.uploads-container{background-color:#2f343a;border:2px solid rgba(0,0,0,.3);border-radius:5px;margin-left:0;margin-right:0;max-width:none;visibility:hidden}
|
||||
.btn-secondary,.btn-secondary:hover,.btn-secondary:focus{color:#333;text-shadow:none}body{background:url(../../assets/background.jpg)no-repeat 50% fixed;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-pack:center;-webkit-box-pack:center;justify-content:center}td{vertical-align:middle;position:relative}a{color:inherit}a:hover{color:inherit;filter:brightness(80%)}.dropzone{background:#2f343a!important;color:#fff;border-radius:5px}.dropzone:hover{background:#33393f!important;color:#fff;border-radius:5px}.card{margin:0 auto;float:none;margin-bottom:10px;border:2px solid #33393f}.card-body{background-color:#212529;color:#ddd}.card-title{font-weight:900}.admin-input{text-align:center}.form-control:disabled{background:#bababa}.break{flex-basis:100%;height:0}.bd-placeholder-img{font-size:1.125rem;text-anchor:middle;-webkit-user-select:none;-moz-user-select:none;user-select:none}@media(min-width:768px){.bd-placeholder-img-lg{font-size:3.5rem}.break{flex-basis:0}}.masthead{margin-bottom:2rem}.masthead-brand{margin-bottom:0}.nav-masthead .nav-link{padding:.25rem 0;font-weight:700;color:rgba(255,255,255,.5);background-color:transparent;border-bottom:.25rem solid transparent}.nav-masthead .nav-link:hover,.nav-masthead .nav-link:focus{border-bottom-color:rgba(255,255,255,.25)}.nav-masthead .nav-link+.nav-link{margin-left:1rem}.nav-masthead .active{color:#fff;border-bottom-color:#fff}#qroverlay{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.3)}#qrcode{position:absolute;top:50%;left:50%;margin-top:-105px;margin-left:-105px;width:210px;height:210px;border:5px solid #fff}.toastnotification{pointer-events:none;position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background-color:#333;color:#fff;padding:15px;border-radius:5px;box-shadow:0 2px 5px rgba(0,0,0,.3);opacity:0;transition:opacity .3s ease-in-out;z-index:9999}.toastdeprecation{background-color:#8b0000}.toastnotification.show{opacity:1;pointer-events:auto}.toast-undo{margin-left:20px;color:#4fc3f7;cursor:pointer;text-decoration:underline;font-weight:700;pointer-events:auto}.toast-undo:hover{color:#81d4fa}.toastnotification:not(.show){pointer-events:none!important}.toastnotification:not(.show) .toast-undo{pointer-events:none}.perm-granted{cursor:pointer;color:#0edf00}.perm-notgranted{cursor:pointer;color:#9f9999}.perm-unavailable{color:#525252}.perm-processing{pointer-events:none;color:#e5eb00}.perm-nochange{cursor:default}.prevent-select{-webkit-user-select:none;-ms-user-select:none;user-select:none}.gokapi-dialog{background-color:#212529;color:#ddd}@keyframes subtleHighlight{0%{background-color:#444950}100%{background-color:transparent}}@keyframes subtleHighlightNewJson{0%{background-color:green}100%{background-color:transparent}}.updatedDownloadCount{animation:subtleHighlight .5s ease-out}.newApiKey{animation:subtleHighlightNewJson .7s ease-out}.newUser{animation:subtleHighlightNewJson .7s ease-out}.newItem{animation:subtleHighlightNewJson 1.5s ease-out}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.rowDeleting{animation:fadeOut .3s ease-out forwards}.highlighted-password{background-color:#444;color:#ddd;padding:2px 6px;border-radius:4px;font-weight:700;font-family:monospace;display:inline-block;margin-left:8px;border:1px solid #555}.filename{font-weight:700;font-size:14px;margin-bottom:5px}.upload-progress-container{display:flex;align-items:center}.upload-progress-bar{position:relative;height:10px;background-color:#eee;flex:1;margin-right:10px;border-radius:4px}.upload-progress-bar-progress{position:absolute;top:0;left:0;height:100%;background-color:#0a0;border-radius:4px;transition:width .2s ease-in-out}.upload-progress-info{font-size:12px}.us-container{margin-top:10px;margin-bottom:20px}.uploaderror{font-weight:700;color:red;margin-bottom:5px}.uploads-container{background-color:#2f343a;border:2px solid rgba(0,0,0,.3);border-radius:5px;margin-left:0;margin-right:0;max-width:none;visibility:hidden}
|
||||
@@ -966,6 +966,7 @@ function handleUndo(button) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function shareUrl(id) {
|
||||
if (!navigator.share) {
|
||||
return;
|
||||
@@ -977,3 +978,13 @@ function shareUrl(id) {
|
||||
url: url,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function showDeprecationNotice() {
|
||||
let notification = document.getElementById("toastDeprecation");
|
||||
notification.classList.add("show");
|
||||
setTimeout(() => {
|
||||
notification.classList.remove("show");
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -111,6 +111,9 @@
|
||||
File deleted: <span id="toastFilename"></span>
|
||||
<span id="toastUndoButton" class="toast-undo" onclick="handleUndo(this)">Restore</span>
|
||||
</div>
|
||||
<div id="toastDeprecation" class="toastnotification toastdeprecation">
|
||||
Warning! This server is using a deprecated feature. Detailed information can be found in the system logs.
|
||||
</div>
|
||||
<div id="qroverlay">
|
||||
<div id="qrcode"></div>
|
||||
</div>
|
||||
@@ -155,6 +158,9 @@
|
||||
var canReplaceOwnFiles = {{.ActiveUser.HasPermissionReplace}};
|
||||
setUploadDefaults();
|
||||
|
||||
{{ if .ShowDeprecationNotice }}
|
||||
showDeprecationNotice();
|
||||
{{ end }}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -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"}}12{{end}}
|
||||
{{define "js_admin_version"}}13{{end}}
|
||||
{{define "js_dropzone_version"}}5{{end}}
|
||||
{{define "js_e2eversion"}}8{{end}}
|
||||
{{define "css_main"}}5{{end}}
|
||||
Reference in New Issue
Block a user