Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pasty v1.0.0 (stable) #48

Draft
wants to merge 25 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
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
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# Created by https://www.toptal.com/developers/gitignore/api/jetbrains+all,go
# Edit at https://www.toptal.com/developers/gitignore?templates=jetbrains+all,go

Expand Down Expand Up @@ -114,6 +113,4 @@ modules.xml

# End of https://www.toptal.com/developers/gitignore/api/jetbrains+all,go

web/*.gz
data/
.env
.env
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ RUN go build \
FROM gcr.io/distroless/base:latest
WORKDIR /root
COPY --from=build /app/pasty .
COPY web ./web/
COPY internal/web/web ./web/
EXPOSE 8080
CMD ["./pasty"]
18 changes: 1 addition & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,6 @@
# pasty
Pasty is a fast and lightweight code pasting server

## !!! Important deprecation notices !!!

> This version of pasty uses a new field name for the so far called `deletionToken`: `modificationToken`.
> Instances using **PostgreSQL** are **not affected** as a corresponding SQL migration will run before the first startup.
> If you however use **another storage driver** you may have to **update the entries** by hand or using a simple query, depending on your driver as I don't plan to ship migrations for every single storage driver.
> It may be important to know that the **data migrator has been upgraded** too. This may serve as a **convenient workaround** (export data (field will be renamed) and import data with changed field names again).
>
> The old `deletionToken` field will be processed corresponding to these changes but I strongly recommend updating old pastes if possible.

> Additionally, I changed the three `DELETION_TOKEN*`environment variables to their corresponding `MODIFICATION_TOKEN*` ones:
> - `DELETION_TOKENS` -> `MODIFICATION_TOKENS`
> - `DELETION_TOKEN_MASTER` -> `MODIFICATION_TOKEN_MASTER`
> - `DELETION_TOKEN_LENGTH` -> `MODIFICATION_TOKEN_LENGTH`
>
> Again, **the old ones will still work** because I do not want to jumble your configurations. However, **please consider updating** them to stay future-proof ^^.

pasty is a fast and lightweight code pasting server.

## Support

Expand Down
163 changes: 131 additions & 32 deletions cmd/pasty/main.go
Original file line number Diff line number Diff line change
@@ -1,52 +1,151 @@
package main

import (
"log"
"time"

"context"
"errors"
"github.com/lus/pasty/internal/cleanup"
"github.com/lus/pasty/internal/config"
"github.com/lus/pasty/internal/consolecommands"
"github.com/lus/pasty/internal/meta"
"github.com/lus/pasty/internal/reports"
"github.com/lus/pasty/internal/storage"
"github.com/lus/pasty/internal/storage/postgres"
"github.com/lus/pasty/internal/storage/sqlite"
"github.com/lus/pasty/internal/web"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"net/http"
"os"
"os/signal"
"strings"
)

func main() {
// Load the configuration
log.Println("Loading the application configuration...")
config.Load()
// Set up the logger
zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMs
if !meta.IsProdEnvironment() {
log.Logger = log.Output(zerolog.ConsoleWriter{
Out: os.Stderr,
})
log.Warn().Msg("This distribution was compiled for development mode and is thus not meant to be run in production!")
}

// Load the configured storage driver
log.Println("Loading the configured storage driver...")
err := storage.Load()
// Load the configuration
config.Compatibility()
cfg, err := config.Load()
if err != nil {
panic(err)
log.Fatal().Err(err).Msg("Could not load the configuration.")
}
defer func() {
log.Println("Terminating the storage driver...")
err := storage.Current.Terminate()

// Adjust the log level
if !meta.IsProdEnvironment() {
zerolog.SetGlobalLevel(zerolog.DebugLevel)
} else {
level, err := zerolog.ParseLevel(cfg.LogLevel)
if err != nil {
log.Fatalln(err)
log.Warn().Msg("An invalid log level was configured. Falling back to 'info'.")
level = zerolog.InfoLevel
}
zerolog.SetGlobalLevel(level)
}

// Determine the correct storage driver to use
var driver storage.Driver
switch strings.TrimSpace(strings.ToLower(cfg.StorageDriver)) {
case "postgres":
driver = postgres.New(cfg.Postgres.DSN)
break
case "sqlite":
driver = sqlite.New(cfg.SQLite.File)
break
case "file":
// TODO: Readme notice
log.Fatal().Msg("You have configured the legacy 'file' storage driver. This storage driver has been removed in favor of PostgreSQL and SQLite, but the latter one may be a seamless alternative for you. Head over to the projects README for more information.")
break
case "mongodb":
case "s3":
// TODO: Readme notice
log.Fatal().Msg("You have configured a legacy storage driver. This storage driver has been removed in favor of PostgreSQL and SQLite, but the migration process is well-documented. Head over to the projects README for more information.")
break
default:
log.Fatal().Str("driver_name", cfg.StorageDriver).Msg("An invalid storage driver name was given.")
return
}

// Initialize the configured storage driver
log.Info().Str("driver_name", cfg.StorageDriver).Msg("Initializing the storage driver...")
if err := driver.Initialize(context.Background()); err != nil {
log.Fatal().Err(err).Str("driver_name", cfg.StorageDriver).Msg("The storage driver could not be initialized.")
return
}
defer func() {
log.Info().Msg("Shutting down the storage driver...")
if err := driver.Close(); err != nil {
log.Err(err).Str("driver_name", cfg.StorageDriver).Msg("Could not shut down the storage driver.")
}
}()

// Schedule the AutoDelete task
if config.Current.AutoDelete.Enabled {
log.Println("Scheduling the AutoDelete task...")
go func() {
for {
// Run the cleanup sequence
deleted, err := storage.Current.Cleanup()
if err != nil {
log.Fatalln(err)
}
log.Printf("AutoDelete: Deleted %d expired pastes", deleted)

// Wait until the process should repeat
time.Sleep(config.Current.AutoDelete.TaskInterval)
}
// Schedule the cleanup task if configured
if cfg.Cleanup.Enabled {
task := &cleanup.Task{
Interval: cfg.Cleanup.TaskInterval,
MaxPasteAge: cfg.Cleanup.PasteLifetime,
Repository: driver.Pastes(),
}
log.Info().Msg("Scheduling the cleanup task...")
task.Start()
defer func() {
log.Info().Msg("Shutting down the cleanup task...")
task.Stop()
}()
}

// Serve the web resources
log.Println("Serving the web resources...")
panic(web.Serve())
// Start the web server
log.Info().Str("address", cfg.Address).Msg("Starting the web server...")
webServer := &web.Server{
Address: cfg.Address,
Storage: driver,
PasteIDLength: cfg.PasteIDLength,
PasteIDCharset: cfg.PasteIDCharset,
PasteLengthCap: cfg.PasteLengthCap,
ModificationTokensEnabled: cfg.ModificationTokensEnabled,
ModificationTokenLength: cfg.ModificationTokenLength,
ModificationTokenCharset: cfg.ModificationTokenCharset,
}
if cfg.Reports.Enabled {
webServer.ReportClient = &reports.Client{
WebhookURL: cfg.Reports.WebhookURL,
WebhookToken: cfg.Reports.WebhookToken,
}
}
if cfg.ModificationTokenMaster != "" {
webServer.AdminTokens = []string{cfg.ModificationTokenMaster}
}
go func() {
if err := webServer.Start(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal().Err(err).Msg("Could not start the web server.")
}
}()
defer func() {
log.Info().Msg("Shutting down the web server...")
if err := webServer.Shutdown(context.Background()); err != nil {
log.Err(err).Msg("Could not shut down the web server.")
}
}()

// Listen to console commands if enabled
if !cfg.ConsoleCommandsEnabled {
log.Info().Msg("The application has been started. Use Ctrl+C to shut it down.")
} else {
log.Info().Msg("The application has been started and listens to console commands. Use Ctrl+C or 'stop' to shut it down.")
go (&consolecommands.Router{
Config: cfg,
Storage: driver,
}).Listen()
}

// Wait for an interrupt signal
shutdownChan := make(chan os.Signal, 1)
signal.Notify(shutdownChan, os.Interrupt)
<-shutdownChan
}
82 changes: 0 additions & 82 deletions cmd/transfer/main.go

This file was deleted.

58 changes: 40 additions & 18 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,23 +1,45 @@
module github.com/lus/pasty

go 1.16
go 1.20

require (
github.com/alexedwards/argon2id v0.0.0-20200802152012-2464efd3196b
github.com/fasthttp/router v1.2.4
github.com/go-stack/stack v1.8.1 // indirect
github.com/golang-migrate/migrate/v4 v4.14.2-0.20201125065321-a53e6fc42574
github.com/golang/snappy v0.0.4 // indirect
github.com/jackc/pgx/v4 v4.11.0
github.com/johejo/golang-migrate-extra v0.0.0-20210217013041-51a992e50d16
github.com/joho/godotenv v1.3.0
github.com/klauspost/compress v1.15.1 // indirect
github.com/minio/minio-go/v7 v7.0.5
github.com/ulule/limiter/v3 v3.5.0
github.com/valyala/fasthttp v1.16.0
github.com/xdg-go/scram v1.1.1 // indirect
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
go.mongodb.org/mongo-driver v1.8.4
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
github.com/alexedwards/argon2id v0.0.0-20230305115115-4b3c3280a736
github.com/go-chi/chi/v5 v5.0.8
github.com/golang-migrate/migrate/v4 v4.16.1
github.com/jackc/pgx/v5 v5.3.1
github.com/joho/godotenv v1.5.1
github.com/kelseyhightower/envconfig v1.4.0
github.com/rs/zerolog v1.29.1
modernc.org/sqlite v1.23.1
)

require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/puddle/v2 v2.2.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
go.uber.org/atomic v1.11.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/tools v0.9.1 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect
modernc.org/ccgo/v3 v3.16.13 // indirect
modernc.org/libc v1.22.5 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/strutil v1.1.3 // indirect
modernc.org/token v1.0.1 // indirect
)
Loading