diff --git a/README.md b/README.md index 4bd6d40..0980ab2 100644 --- a/README.md +++ b/README.md @@ -72,17 +72,19 @@ Pasty will be available at http://localhost:8080. --- ## General environment variables -| Environment Variable | Default Value | Type | Description | -|-----------------------------------|---------------|----------|----------------------------------------------------------------------------------------------------------------------------| -| `PASTY_WEB_ADDRESS` | `:8080` | `string` | Defines the address the web server listens to | -| `PASTY_STORAGE_TYPE` | `file` | `string` | Defines the storage type the pastes are saved to | -| `PASTY_HASTEBIN_SUPPORT` | `false` | `bool` | Defines whether or not the `POST /documents` endpoint should be enabled, as known from the hastebin servers | -| `PASTY_ID_LENGTH` | `6` | `number` | Defines the length of the ID of a paste | -| `PASTY_MODIFICATION_TOKENS` | `true` | `bool` | Defines whether or not modification tokens should be generated | -| `PASTY_MODIFICATION_TOKEN_MASTER` | `` | `string` | Defines the master modification token which is authorized to modify every paste (even if modification tokens are disabled) | -| `PASTY_MODIFICATION_TOKEN_LENGTH` | `12` | `number` | Defines the length of the modification token of a paste | -| `PASTY_RATE_LIMIT` | `30-M` | `string` | Defines the rate limit of the API (see https://github.com/ulule/limiter#usage) | -| `PASTY_LENGTH_CAP` | `50000` | `number` | Defines the maximum amount of characters a paste is allowed to contain (a value `<= 0` means no limit) | +| Environment Variable | Default Value | Type | Description | +|---------------------------------------|------------------------------------------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------| +| `PASTY_WEB_ADDRESS` | `:8080` | `string` | Defines the address the web server listens to | +| `PASTY_STORAGE_TYPE` | `file` | `string` | Defines the storage type the pastes are saved to | +| `PASTY_HASTEBIN_SUPPORT` | `false` | `bool` | Defines whether or not the `POST /documents` endpoint should be enabled, as known from the hastebin servers | +| `PASTY_ID_LENGTH` | `6` | `number` | Defines the length of the ID of a paste | +| `PASTY_ID_CHARACTERS` | `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789` | `string` | Defines the characters to use when generating paste IDs | +| `PASTY_MODIFICATION_TOKENS` | `true` | `bool` | Defines whether or not modification tokens should be generated | +| `PASTY_MODIFICATION_TOKEN_MASTER` | `` | `string` | Defines the master modification token which is authorized to modify every paste (even if modification tokens are disabled) | +| `PASTY_MODIFICATION_TOKEN_LENGTH` | `12` | `number` | Defines the length of the modification token of a paste | +| `PASTY_MODIFICATION_TOKEN_CHARACTERS` | `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789` | `string` | Defines the characters to use when generating modification tokens | +| `PASTY_RATE_LIMIT` | `30-M` | `string` | Defines the rate limit of the API (see https://github.com/ulule/limiter#usage) | +| `PASTY_LENGTH_CAP` | `50000` | `number` | Defines the maximum amount of characters a paste is allowed to contain (a value `<= 0` means no limit) | ## AutoDelete Pasty provides an intuitive system to automatically delete pastes after a specific amount of time. You can configure it with the following variables: diff --git a/internal/config/config.go b/internal/config/config.go index 2172d2e..6254e28 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -10,21 +10,23 @@ import ( // Config represents the general application configuration structure type Config struct { - WebAddress string - StorageType shared.StorageType - HastebinSupport bool - IDLength int - ModificationTokens bool - ModificationTokenMaster string - ModificationTokenLength int - RateLimit string - LengthCap int - AutoDelete *AutoDeleteConfig - Reports *ReportConfig - File *FileConfig - Postgres *PostgresConfig - MongoDB *MongoDBConfig - S3 *S3Config + WebAddress string + StorageType shared.StorageType + HastebinSupport bool + IDLength int + IDCharacters string + ModificationTokens bool + ModificationTokenMaster string + ModificationTokenLength int + ModificationTokenCharacters string + RateLimit string + LengthCap int + AutoDelete *AutoDeleteConfig + Reports *ReportConfig + File *FileConfig + Postgres *PostgresConfig + MongoDB *MongoDBConfig + S3 *S3Config } // AutoDeleteConfig represents the configuration specific for the AutoDelete behaviour @@ -77,15 +79,17 @@ func Load() { env.Load() Current = &Config{ - WebAddress: env.MustString("WEB_ADDRESS", ":8080"), - StorageType: shared.StorageType(strings.ToLower(env.MustString("STORAGE_TYPE", "file"))), - HastebinSupport: env.MustBool("HASTEBIN_SUPPORT", false), - IDLength: env.MustInt("ID_LENGTH", 6), - ModificationTokens: env.MustBool("MODIFICATION_TOKENS", env.MustBool("DELETION_TOKENS", true)), // --- - ModificationTokenMaster: env.MustString("MODIFICATION_TOKEN_MASTER", env.MustString("DELETION_TOKEN_MASTER", "")), // - We don't want to destroy peoples old configuration - ModificationTokenLength: env.MustInt("MODIFICATION_TOKEN_LENGTH", env.MustInt("DELETION_TOKEN_LENGTH", 12)), // --- - RateLimit: env.MustString("RATE_LIMIT", "30-M"), - LengthCap: env.MustInt("LENGTH_CAP", 50_000), + WebAddress: env.MustString("WEB_ADDRESS", ":8080"), + StorageType: shared.StorageType(strings.ToLower(env.MustString("STORAGE_TYPE", "file"))), + HastebinSupport: env.MustBool("HASTEBIN_SUPPORT", false), + IDLength: env.MustInt("ID_LENGTH", 6), + IDCharacters: env.MustString("ID_CHARACTERS", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"), + ModificationTokens: env.MustBool("MODIFICATION_TOKENS", env.MustBool("DELETION_TOKENS", true)), // --- + ModificationTokenMaster: env.MustString("MODIFICATION_TOKEN_MASTER", env.MustString("DELETION_TOKEN_MASTER", "")), // - We don't want to destroy peoples old configuration + ModificationTokenLength: env.MustInt("MODIFICATION_TOKEN_LENGTH", env.MustInt("DELETION_TOKEN_LENGTH", 12)), // --- + ModificationTokenCharacters: env.MustString("MODIFICATION_TOKEN_CHARACTERS", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"), + RateLimit: env.MustString("RATE_LIMIT", "30-M"), + LengthCap: env.MustInt("LENGTH_CAP", 50_000), AutoDelete: &AutoDeleteConfig{ Enabled: env.MustBool("AUTODELETE", false), Lifetime: env.MustDuration("AUTODELETE_LIFETIME", 720*time.Hour), diff --git a/internal/storage/id_generation.go b/internal/storage/id_generation.go index a3b6c58..99b05eb 100644 --- a/internal/storage/id_generation.go +++ b/internal/storage/id_generation.go @@ -8,7 +8,7 @@ import ( // AcquireID generates a new unique ID func AcquireID() (string, error) { for { - id := utils.RandomString(config.Current.IDLength) + id := utils.RandomString(config.Current.IDCharacters, config.Current.IDLength) paste, err := Current.Get(id) if err != nil { return "", err diff --git a/internal/utils/random_string.go b/internal/utils/random_string.go index 1f927a5..3798ec5 100644 --- a/internal/utils/random_string.go +++ b/internal/utils/random_string.go @@ -5,15 +5,12 @@ import ( "time" ) -// stringContents holds the chars a random string can contain -const stringContents = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - // RandomString returns a random string with the given length -func RandomString(length int) string { +func RandomString(characters string, length int) string { rand.Seed(time.Now().UnixNano()) bytes := make([]byte, length) for i := range bytes { - bytes[i] = stringContents[rand.Int63()%int64(len(stringContents))] + bytes[i] = characters[rand.Int63()%int64(len(characters))] } return string(bytes) } diff --git a/internal/web/controllers/v1/hastebin_support.go b/internal/web/controllers/v1/hastebin_support.go index 08b1fbf..3f12f0f 100644 --- a/internal/web/controllers/v1/hastebin_support.go +++ b/internal/web/controllers/v1/hastebin_support.go @@ -52,7 +52,7 @@ func HastebinSupportHandler(ctx *fasthttp.RequestCtx) { // Set a modification token if config.Current.ModificationTokens { - paste.ModificationToken = utils.RandomString(config.Current.ModificationTokenLength) + paste.ModificationToken = utils.RandomString(config.Current.ModificationTokenCharacters, config.Current.ModificationTokenLength) err = paste.HashModificationToken() if err != nil { diff --git a/internal/web/controllers/v1/pastes.go b/internal/web/controllers/v1/pastes.go index 3e617ca..4f8c20c 100644 --- a/internal/web/controllers/v1/pastes.go +++ b/internal/web/controllers/v1/pastes.go @@ -95,7 +95,7 @@ func v1PostPaste(ctx *fasthttp.RequestCtx) { // Set a modification token modificationToken := "" if config.Current.ModificationTokens { - modificationToken = utils.RandomString(config.Current.ModificationTokenLength) + modificationToken = utils.RandomString(config.Current.ModificationTokenCharacters, config.Current.ModificationTokenLength) paste.ModificationToken = modificationToken err = paste.HashModificationToken() diff --git a/internal/web/controllers/v2/pastes.go b/internal/web/controllers/v2/pastes.go index 4ef7829..80100ef 100644 --- a/internal/web/controllers/v2/pastes.go +++ b/internal/web/controllers/v2/pastes.go @@ -146,7 +146,7 @@ func endpointCreatePaste(ctx *fasthttp.RequestCtx) { // Create a new modification token if enabled modificationToken := "" if config.Current.ModificationTokens { - modificationToken = utils.RandomString(config.Current.ModificationTokenLength) + modificationToken = utils.RandomString(config.Current.ModificationTokenCharacters, config.Current.ModificationTokenLength) paste.ModificationToken = modificationToken err = paste.HashModificationToken()