9 files changed,
245 insertions(+),
2 deletions(-)
Author:
Smirnov Oleksandr
ss2316544@gmail.com
Committed by:
GitHub
noreply@github.com
Committed at:
2025-05-30 15:58:02 +0300
Parent:
c685a65
M
.env.example
··· 34 34 POSTGRES_DATABASE=onasty 35 35 POSTGRESQL_DSN="postgres://$POSTGRES_USERNAME:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DATABASE?sslmode=disable" 36 36 MIGRATION_DSN="postgres://$POSTGRES_USERNAME:$POSTGRES_PASSWORD@localhost:$POSTGRES_PORT/$POSTGRES_DATABASE?sslmode=disable" 37 +SEED_DSN=$MIGRATION_DSN 37 38 38 39 REDIS_ADDR="redis:6379" 39 40 CACHE_USERS_TTL=1h
M
.github/workflows/golang.yml
··· 21 21 cache-dependency-path: go.mod 22 22 23 23 - name: Build API 24 - run: go build -o .bin/onasty ./cmd/server/ 24 + run: go build -o .bin/onasty ./cmd/api/ 25 + 26 + - name: Build mailer service 27 + run: go build -o .bin/mailer ./mailer/ 25 28 26 29 - name: Unit tests 27 30 run: go test -v --short ./...
M
Dockerfile
··· 11 11 ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64 12 12 RUN --mount=type=cache,target=/root/.cache/go-build,id=onasty-go-build \ 13 13 --mount=type=cache,target=/go/pkg/mod,id=onasty-go-mod \ 14 - go build -trimpath -ldflags='-w -s' -o /onasty ./cmd/server 14 + go build -trimpath -ldflags='-w -s' -o /onasty ./cmd/api 15 15 16 16 FROM onasty:runtime 17 17 COPY --from=builder /onasty /onasty
A
cmd/seed/main.go
··· 1 +package main 2 + 3 +import ( 4 + "context" 5 + "fmt" 6 + "log/slog" 7 + "os" 8 + 9 + "github.com/olexsmir/onasty/internal/config" 10 + "github.com/olexsmir/onasty/internal/hasher" 11 + "github.com/olexsmir/onasty/internal/logger" 12 + "github.com/olexsmir/onasty/internal/store/psqlutil" 13 +) 14 + 15 +func main() { 16 + if err := run(context.Background()); err != nil { 17 + fmt.Fprintf(os.Stderr, "error: %v\n", err) 18 + os.Exit(1) 19 + } 20 +} 21 + 22 +func run(ctx context.Context) error { 23 + cfg := config.NewConfig() 24 + cfg.PostgresDSN = os.Getenv("SEED_DSN") 25 + 26 + logger, err := logger.NewCustomLogger(cfg.LogLevel, cfg.LogFormat, cfg.LogShowLine) 27 + if err != nil { 28 + return err 29 + } 30 + slog.SetDefault(logger) 31 + 32 + psql, err := psqlutil.Connect(ctx, cfg.PostgresDSN) 33 + if err != nil { 34 + return err 35 + } 36 + 37 + userHasher := hasher.NewSHA256Hasher(cfg.PasswordSalt) 38 + noteHasher := hasher.NewSHA256Hasher(cfg.NotePasswordSalt) 39 + 40 + if err := seedUsers(ctx, userHasher, psql); err != nil { 41 + return fmt.Errorf("failed to seed users: %w", err) 42 + } 43 + 44 + slog.Info("Users seeded successfully") 45 + 46 + if err := seedNotes(ctx, noteHasher, psql); err != nil { 47 + return fmt.Errorf("failed to seed notes: %w", err) 48 + } 49 + 50 + slog.Info("Notes seeded successfully") 51 + 52 + return nil 53 +}
A
cmd/seed/notes.go
··· 1 +package main 2 + 3 +import ( 4 + "context" 5 + "log/slog" 6 + "time" 7 + 8 + "github.com/olexsmir/onasty/internal/hasher" 9 + "github.com/olexsmir/onasty/internal/store/psqlutil" 10 +) 11 + 12 +var notesData = []struct { 13 + id string 14 + content string 15 + slug string 16 + burnBeforeExpiration bool 17 + password string 18 + expiresAt time.Time 19 + hasAuthor bool 20 + authorID int 21 +}{ 22 + { //nolint:exhaustruct 23 + content: "that test note one", 24 + slug: "one", 25 + burnBeforeExpiration: false, 26 + }, 27 + { //nolint:exhaustruct 28 + content: "that test note two", 29 + slug: "two", 30 + burnBeforeExpiration: true, 31 + password: "", 32 + expiresAt: time.Now().Add(24 * time.Hour), 33 + }, 34 + { //nolint:exhaustruct 35 + content: "that passworded note", 36 + slug: "passwd", 37 + burnBeforeExpiration: false, 38 + password: "pass", 39 + }, 40 + { //nolint:exhaustruct 41 + content: "that note with author", 42 + slug: "user", 43 + burnBeforeExpiration: false, 44 + hasAuthor: true, 45 + authorID: 0, 46 + }, 47 + { //nolint:exhaustruct 48 + content: "that another authored note", 49 + slug: "user2", 50 + burnBeforeExpiration: false, 51 + hasAuthor: true, 52 + authorID: 0, 53 + }, 54 + { //nolint:exhaustruct 55 + content: "that another authored note", 56 + slug: "user2", 57 + password: "passwd", 58 + burnBeforeExpiration: false, 59 + hasAuthor: true, 60 + authorID: 0, 61 + }, 62 +} 63 + 64 +func seedNotes( 65 + ctx context.Context, 66 + hash hasher.Hasher, 67 + db *psqlutil.DB, 68 +) error { 69 + for i, note := range notesData { 70 + passwd := "" 71 + if note.password != "" { 72 + var err error 73 + passwd, err = hash.Hash(note.password) 74 + if err != nil { 75 + return err 76 + } 77 + } 78 + 79 + err := db.QueryRow( 80 + ctx, ` 81 + insert into notes (content, slug, burn_before_expiration, password, expires_at) 82 + values ($1, $2, $3, $4, $5) 83 + on conflict (slug) do update set 84 + content = excluded.content, 85 + burn_before_expiration = excluded.burn_before_expiration, 86 + password = excluded.password, 87 + expires_at = excluded.expires_at 88 + returning id`, 89 + note.content, 90 + note.slug, 91 + note.burnBeforeExpiration, 92 + passwd, 93 + note.expiresAt, 94 + ).Scan(¬esData[i].id) 95 + if err != nil { 96 + return err 97 + } 98 + 99 + if note.hasAuthor { 100 + slog.Info("setting author", "note", note.id, "author", note.authorID) 101 + if err := setAuthor(ctx, db, notesData[i].id, usersData[note.authorID].id); err != nil { 102 + return err 103 + } 104 + } 105 + } 106 + 107 + return nil 108 +} 109 + 110 +func setAuthor( 111 + ctx context.Context, 112 + db *psqlutil.DB, 113 + noteID string, 114 + authorID string, 115 +) error { 116 + _, err := db.Exec( 117 + ctx, 118 + `insert into notes_authors (note_id, user_id) values ($1, $2)`, 119 + noteID, authorID) 120 + return err 121 +}
A
cmd/seed/users.go
··· 1 +package main 2 + 3 +import ( 4 + "context" 5 + "time" 6 + 7 + "github.com/jackc/pgx/v5/pgtype" 8 + "github.com/olexsmir/onasty/internal/hasher" 9 + "github.com/olexsmir/onasty/internal/store/psqlutil" 10 +) 11 + 12 +var usersData = []struct { 13 + id string 14 + email string 15 + password string 16 + activated bool 17 +}{ 18 + { //nolint:exhaustruct 19 + email: "admin@onasty.local", 20 + password: "adminadmin", 21 + activated: true, 22 + }, 23 + { //nolint:exhaustruct 24 + email: "users@onasty.local", 25 + activated: false, 26 + password: "qwerty123", 27 + }, 28 +} 29 + 30 +func seedUsers( 31 + ctx context.Context, 32 + hash hasher.Hasher, 33 + db *psqlutil.DB, 34 +) error { 35 + for i, user := range usersData { 36 + passwrd, err := hash.Hash(user.password) 37 + if err != nil { 38 + return err 39 + } 40 + 41 + var id pgtype.UUID 42 + err = db.QueryRow(ctx, ` 43 + insert into users (email, password, activated, created_at, last_login_at) 44 + values ($1, $2, $3, $4, $5) 45 + on conflict (email) do update 46 + set password = excluded.password 47 + returning id 48 + `, user.email, passwrd, user.activated, time.Now(), time.Now()). 49 + Scan(&id) 50 + if err != nil { 51 + return err 52 + } 53 + 54 + usersData[i].id = id.String() 55 + } 56 + 57 + return nil 58 +}