119 lines
2.8 KiB
Go
119 lines
2.8 KiB
Go
// Command seed creates demo users, a family group and a few messages.
|
|||
|
|
// It is idempotent: existing usernames are left untouched.
|
||
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"fmt"
|
||
|
|
"os"
|
||
|
|
|
||
|
|
"messenger/internal/auth"
|
||
|
|
"messenger/internal/platform/config"
|
||
|
|
"messenger/internal/platform/logger"
|
||
|
|
"messenger/internal/store"
|
||
|
|
|
||
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
||
|
|
)
|
||
|
|
|
||
|
|
type seedUser struct {
|
||
|
|
username string
|
||
|
|
displayName string
|
||
|
|
password string
|
||
|
|
}
|
||
|
|
|
||
|
|
var demoUsers = []seedUser{
|
||
|
|
{"papa", "Папа", "password123"},
|
||
|
|
{"mama", "Мама", "password123"},
|
||
|
|
{"syn", "Сын", "password123"},
|
||
|
|
{"doch", "Дочь", "password123"},
|
||
|
|
}
|
||
|
|
|
||
|
|
func main() {
|
||
|
|
log := logger.New()
|
||
|
|
cfg, err := config.Load()
|
||
|
|
if err != nil {
|
||
|
|
log.Error("invalid configuration", "error", err)
|
||
|
|
os.Exit(1)
|
||
|
|
}
|
||
|
|
ctx := context.Background()
|
||
|
|
pool, err := pgxpool.New(ctx, cfg.DatabaseURL)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("failed to connect", "error", err)
|
||
|
|
os.Exit(1)
|
||
|
|
}
|
||
|
|
defer pool.Close()
|
||
|
|
|
||
|
|
st := store.New(pool)
|
||
|
|
if err := st.Migrate(ctx); err != nil {
|
||
|
|
log.Error("migration failed", "error", err)
|
||
|
|
os.Exit(1)
|
||
|
|
}
|
||
|
|
|
||
|
|
created, err := ensureUsers(ctx, st)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("seed users failed", "error", err)
|
||
|
|
os.Exit(1)
|
||
|
|
}
|
||
|
|
fmt.Printf("users created: %d\n", created)
|
||
|
|
|
||
|
|
group, err := ensureGroup(ctx, st)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("seed group failed", "error", err)
|
||
|
|
os.Exit(1)
|
||
|
|
}
|
||
|
|
fmt.Printf("group ready: %s (id=%d)\n", group.Name, group.ID)
|
||
|
|
}
|
||
|
|
|
||
|
|
func ensureUsers(ctx context.Context, st *store.Store) (int, error) {
|
||
|
|
created := 0
|
||
|
|
for _, u := range demoUsers {
|
||
|
|
if _, err := st.GetUserByUsername(ctx, u.username); err == nil {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
hash, err := auth.HashPassword(u.password)
|
||
|
|
if err != nil {
|
||
|
|
return created, err
|
||
|
|
}
|
||
|
|
if _, err := st.CreateUser(ctx, u.username, u.displayName, hash); err != nil {
|
||
|
|
return created, err
|
||
|
|
}
|
||
|
|
created++
|
||
|
|
}
|
||
|
|
return created, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func ensureGroup(ctx context.Context, st *store.Store) (*store.Conversation, error) {
|
||
|
|
users := make([]int64, 0, len(demoUsers))
|
||
|
|
var ownerID int64
|
||
|
|
for _, u := range demoUsers {
|
||
|
|
user, err := st.GetUserByUsername(ctx, u.username)
|
||
|
|
if err != nil {
|
||
|
|
return nil, fmt.Errorf("user %s missing: %w", u.username, err)
|
||
|
|
}
|
||
|
|
if ownerID == 0 {
|
||
|
|
ownerID = user.ID
|
||
|
|
}
|
||
|
|
users = append(users, user.ID)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Reuse an existing group with the same name if present.
|
||
|
|
conversations, err := st.ListConversationsForUser(ctx, ownerID)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
for i := range conversations {
|
||
|
|
if conversations[i].Type == "group" && conversations[i].Name == "Семья" {
|
||
|
|
return &conversations[i].Conversation, nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
group, err := st.CreateGroup(ctx, ownerID, "Семья", users[1:])
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
if _, err := st.InsertMessage(ctx, group.ID, ownerID, "Всем привет! Это наша семейная группа.", nil); err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
return group, nil
|
||
|
|
}
|