120 lines
2.8 KiB
Go
120 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rand"
|
|
"embed"
|
|
"encoding/base64"
|
|
"flag"
|
|
"log"
|
|
"os"
|
|
|
|
"git.codemonkeysoftware.net/mouseion/server/pkg/authentication"
|
|
"git.codemonkeysoftware.net/mouseion/server/pkg/authentication/apitoken"
|
|
authstore "git.codemonkeysoftware.net/mouseion/server/pkg/authentication/sql_store"
|
|
"git.codemonkeysoftware.net/mouseion/server/pkg/database"
|
|
"git.codemonkeysoftware.net/mouseion/server/pkg/database/sqlite"
|
|
"git.codemonkeysoftware.net/mouseion/server/pkg/email"
|
|
entrystore "git.codemonkeysoftware.net/mouseion/server/pkg/entry/sql_store"
|
|
"git.codemonkeysoftware.net/mouseion/server/pkg/views"
|
|
"git.codemonkeysoftware.net/mouseion/server/pkg/webserver"
|
|
|
|
"github.com/JeremyLoy/config"
|
|
"github.com/volatiletech/authboss/v3"
|
|
)
|
|
|
|
//go:embed public/*
|
|
var public embed.FS
|
|
|
|
type Config struct {
|
|
Auth authentication.Config
|
|
Database database.Config
|
|
Email email.Config
|
|
}
|
|
|
|
func main() {
|
|
var configPath string
|
|
flag.StringVar(&configPath, "config", "", "")
|
|
flag.Parse()
|
|
appConfig := Config{}
|
|
config := config.FromEnv()
|
|
if configPath != "" {
|
|
log.Printf("using config from %s", configPath)
|
|
config.From(configPath)
|
|
}
|
|
err := config.To(&appConfig)
|
|
if err != nil {
|
|
log.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
db := sqlite.Open(appConfig.Database.Path)
|
|
defer db.Close()
|
|
err = sqlite.DoMigrations(db.DB)
|
|
if err != nil {
|
|
log.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
entryService := entrystore.New(db)
|
|
authStorer := authstore.New(db)
|
|
ab, err := authentication.Authboss(authStorer, appConfig.Auth, appConfig.Email)
|
|
if err != nil {
|
|
log.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
apiToken := apitoken.APIToken{Authboss: ab}
|
|
apiToken.Setup()
|
|
|
|
adminUser, err := createFirstAdminUser(authStorer, ab)
|
|
if err != nil {
|
|
log.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
if adminUser != nil {
|
|
log.Printf("Created first admin user\nEmail: %s\nPassword: %s", adminUser.Email, adminUser.Password)
|
|
}
|
|
webserver.New(
|
|
entryService,
|
|
authStorer,
|
|
ab,
|
|
authStorer,
|
|
apiToken.RequireTokenMiddleware,
|
|
views.WebTemplates(),
|
|
public,
|
|
).Start()
|
|
}
|
|
|
|
func createFirstAdminUser(authStorer *authstore.SQLStore, ab *authboss.Authboss) (*authentication.User, error) {
|
|
ctx := context.Background()
|
|
err := authStorer.UsersExist(ctx)
|
|
if err == nil {
|
|
return nil, nil
|
|
}
|
|
if err != authstore.ErrNoUsers {
|
|
return nil, err
|
|
}
|
|
abUser := authStorer.New(ctx)
|
|
adminUser, err := authentication.GetAuthUser(abUser)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
adminUser.Email = "tinyhatchet@example.com"
|
|
adminUser.Confirmed = true
|
|
err = authStorer.Create(ctx, adminUser)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
passBuff := make([]byte, 15)
|
|
_, err = rand.Read(passBuff)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
password := base64.StdEncoding.EncodeToString(passBuff)
|
|
err = ab.UpdatePassword(ctx, adminUser, password)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
adminUser.Password = password
|
|
return adminUser, nil
|
|
}
|