Several fixes and features
All checks were successful
/ pre-commit (push) Successful in 1m8s

- Commit database transactions
- Listen to all interfaces by default
- Use logger in collerd
- Add docker-compose file with PostgreSQL

Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
Julien Riou 2025-08-26 12:28:32 +02:00
parent 01031a24ab
commit 7d7614637b
Signed by: jriou
GPG key ID: 9A099EDA51316854
7 changed files with 45 additions and 6 deletions

31
docker-compose.yml Normal file
View file

@ -0,0 +1,31 @@
---
services:
server:
image: coller:latest
build: .
container_name: collerd
restart: always
networks:
- coller
ports:
- "8080:8080"
volumes:
- "./docker/collerd.json:/etc/collerd.json:ro"
command: collerd -config /etc/collerd.json
db:
image: postgres:17
hostname: db
container_name: collerd_db
restart: always
env_file: docker/db.env
networks:
- coller
volumes:
- coller:/var/lib/postgresql/data
networks:
coller:
volumes:
coller:

5
docker/db.env Normal file
View file

@ -0,0 +1,5 @@
POSTGRES_USER=coller
POSTGRES_PASSWORD=wwav93psLNc9RFrMNCYiixLqkxCMFMnm
POSTGRES_DB=coller
POSTGRES_INITDB_ARGS="--data-checksums"
POSTGRES_HOST_AUTH_METHOD=scram-sha-256

View file

@ -21,7 +21,7 @@ The file format is **JSON**:
* **id_length** (int): Number of characters for note identifiers (default 5)
* **password_length** (int): Number of characters for generated passwords (default 16)
* **expiration_interval** (int): Number of seconds to wait between two expiration runs
* **listen_address** (string): Address to listen for the web server (default "127.0.0.1")
* **listen_address** (string): Address to listen for the web server (default "0.0.0.0")
* **listen_port** (int): Port to listen for the web server (default 8080)
* **expirations** ([]int): List of supported expiration times in seconds (default 300, 86400, 604800, 18144000)
* **expiration** (int): Default expiration time in seconds

View file

@ -50,7 +50,7 @@ func handleMain() int {
if *configFileName != "" {
err = internal.ReadConfig(*configFileName, config)
if err != nil {
slog.Error("cannot parse configuration file", slog.Any("error", err))
logger.Error("cannot parse configuration file", slog.Any("error", err))
return internal.RC_ERROR
}
logger.Debug("configuration file parsed", slog.Any("file", *configFileName))
@ -63,7 +63,7 @@ func handleMain() int {
db, err := server.NewDatabase(logger, config)
if err != nil {
slog.Error("could not connect to the database", slog.Any("error", err))
logger.Error("could not connect to the database", slog.Any("error", err))
return internal.RC_ERROR
}

View file

@ -33,7 +33,7 @@ func NewConfig() *Config {
IDLength: 5,
PasswordLength: 16,
ExpirationInterval: 60, // 1 minute
ListenAddress: "127.0.0.1",
ListenAddress: "0.0.0.0",
ListenPort: 8080,
Expirations: []int{
300, // 5 minutes

View file

@ -93,6 +93,7 @@ func (d *Database) StartExpireThread() {
func (d *Database) Get(id string) (*Note, error) {
var note Note
trx := d.db.Where("id = ?", id).Find(&note)
defer trx.Commit()
if trx.Error != nil {
d.logger.Warn("could not find note", slog.Any("error", trx.Error))
return nil, trx.Error
@ -134,6 +135,7 @@ func (d *Database) Create(content []byte, password string, encrypted bool, expir
note.Encrypted = true
}
trx := d.db.Create(note)
defer trx.Commit()
if trx.Error != nil {
d.logger.Warn("could not create note", slog.Any("error", trx.Error))
return nil, trx.Error
@ -143,6 +145,7 @@ func (d *Database) Create(content []byte, password string, encrypted bool, expir
func (d *Database) Delete(id string) error {
trx := d.db.Where("id = ?", id).Delete(&Note{})
defer trx.Commit()
if trx.Error != nil {
d.logger.Error("could not delete note", slog.Any("error", trx.Error))
return trx.Error

View file

@ -21,7 +21,7 @@ type Note struct {
}
// Generate ID and compress content before saving to the database
func (n *Note) BeforeCreate(tx *gorm.DB) (err error) {
func (n *Note) BeforeCreate(trx *gorm.DB) (err error) {
for i := 0; i < ID_MAX_RETRIES; i++ {
if n.ID != "" {
continue
@ -30,7 +30,7 @@ func (n *Note) BeforeCreate(tx *gorm.DB) (err error) {
id := internal.GenerateChars(idLength)
var note Note
tx.Where("id = ?", id).Find(&note)
trx.Where("id = ?", id).Find(&note)
if note.ID == "" {
n.ID = id