4 Commits
0.0.6 ... 0.0.7

Author SHA1 Message Date
Lennart J. Kurzweg (Nx2)
b4a65a1af4 gitignore 2026-04-23 17:33:35 +02:00
Lennart J. Kurzweg (Nx2)
65aeeda263 Merge branch 'master' of ssh://ssh.nx2.site:50022/nx2/nxcaldav 2026-04-23 17:32:33 +02:00
Lennart J. Kurzweg (Nx2)
f61e014d2a smtp pw 2026-04-23 17:32:30 +02:00
ce6a5c7477 Delete shell.nix 2026-04-23 17:21:10 +02:00
7 changed files with 47 additions and 73 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
.direnv
server.log
shell.nix
mem.go
nxcaldav
in/

View File

@@ -3,74 +3,45 @@ database:
server:
bind_address: 0.0.0.0:14243
default_class: CONFIDENTIAL
public_url: http://nxc.nx2.site/
email_domain: nx2.site
public_url: http://example.com/
email_domain: example.com
redaction_text: '[-]'
smtp:
host: localhost
port: 587
user: nxcaldav@nx2.site
password: Vastly-Wrinkle9-Corsage
password_cmd: echo "Vastly-Wrinkle9-Corsage"
users:
- name: daniel
password: ll
- name: alice
password: 123
groups:
- family
- name: lennart
password: ll
- name: bob
password: abc
groups:
- family
- name: shared
password: Oxidant-Ageless3-Dispersed
calendars:
- id: preservation
owner: lennart
- id: test
owner: alice
color: '#F6F5F4'
- id: effort
owner: lennart
color: '#FF0000'
- id: experience
owner: lennart
color: '#2C33FF'
- id: leisure
owner: lennart
color: '#10B400'
- id: daniel
owner: daniel
color: '#ff2222'
- access:
- group: family
mode: read-write
id: family
- id: family
owner: shared
color: '#999999'
access:
- group: family
mode: read-write
address_books:
- id: contacts
owner: lennart
- id: contacts
owner: daniel
owner: alice
- id: family
owner: shared
owner: bob
access:
- group: family
mode: read-write
aggregates:
- access:
- group: family
mode: read-only
- ics: future-only
id: lennart-aggregat
owner: lennart
color: '#dd9999'
sources:
- preservation
- effort
- experience
- leisure
- family

View File

@@ -8,7 +8,6 @@ import (
"log"
"net/http"
"net/url"
"os/exec"
"path"
"slices"
"strings"
@@ -140,16 +139,9 @@ func (b *DBBackend) initSchema(ctx context.Context) error {
}
func (b *DBBackend) resolvePassword(u config.User) (string, error) {
var raw string
if u.PasswordCmd != "" {
cmd := exec.Command("sh", "-c", u.PasswordCmd)
out, err := cmd.Output()
if err != nil {
return "", fmt.Errorf("failed to run password command for %s: %v", u.Name, err)
}
raw = strings.TrimSpace(string(out))
} else {
raw = u.Password
raw, err := config.ResolvePassword(u.Password, u.PasswordCmd)
if err != nil {
return "", fmt.Errorf("failed to resolve password for %s: %v", u.Name, err)
}
// If it already looks like a bcrypt hash, return as is.

View File

@@ -10,6 +10,7 @@ import (
"strings"
"github.com/emersion/go-ical"
"nxcaldav/internal/config"
)
// sendInvitation sends an iMIP (RFC 6047) invitation email.
@@ -99,8 +100,14 @@ func (b *DBBackend) sendInvitation(senderName, recipientEmail, summary, descript
if err = c.StartTLS(tlsConfig); err != nil { return err }
}
}
if b.smtp.User != "" && b.smtp.Password != "" {
auth := smtp.PlainAuth("", b.smtp.User, b.smtp.Password, b.smtp.Host)
smtpPassword, err := config.ResolvePassword(b.smtp.Password, b.smtp.PasswordCmd)
if err != nil {
return fmt.Errorf("failed to resolve SMTP password: %v", err)
}
if b.smtp.User != "" && smtpPassword != "" {
auth := smtp.PlainAuth("", b.smtp.User, smtpPassword, b.smtp.Host)
if err = c.Auth(auth); err != nil { return err }
}

View File

@@ -1,8 +1,10 @@
package config
import (
"fmt"
"net/url"
"os"
"os/exec"
"slices"
"strings"
@@ -64,10 +66,11 @@ func (s ServerConfig) BasePath() string {
type SMTPConfig struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
User string `yaml:"user"`
Password string `yaml:"password"`
Host string `yaml:"host"`
Port int `yaml:"port"`
User string `yaml:"user"`
Password string `yaml:"password"`
PasswordCmd string `yaml:"password_cmd"`
}
type Config struct {
@@ -79,6 +82,18 @@ type Config struct {
AddressBooks []AddressBook `yaml:"address_books"`
Aggregates []Aggregate `yaml:"aggregates"`
}
func ResolvePassword(password, passwordCmd string) (string, error) {
if passwordCmd != "" {
cmd := exec.Command("sh", "-c", passwordCmd)
out, err := cmd.Output()
if err != nil {
return "", fmt.Errorf("failed to run password command: %v", err)
}
return strings.TrimSpace(string(out)), nil
}
return password, nil
}
func (c *Config) setDefaults() {
if c.Server.BindAddress == "" { c.Server.BindAddress = ":8080" }
if c.Server.Redaction == "" { c.Server.Redaction = "Busy" }

BIN
main

Binary file not shown.

View File

@@ -1,12 +0,0 @@
{ pkgs ? import <nixpkgs> { } }: let
my-python = pkgs.python312;
python-with-my-packages = my-python.withPackages (p: with p; [
ical
ics
caldav
pyyaml
psycopg2
]);
in pkgs.mkShell {
buildInputs = [ python-with-my-packages ];
}