aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/cmd/migrate.go110
-rw-r--r--app/cmd/root.go10
-rw-r--r--app/cmd/serve.go53
-rw-r--r--app/cmd/user.go80
4 files changed, 190 insertions, 63 deletions
diff --git a/app/cmd/migrate.go b/app/cmd/migrate.go
index 3c4fd05..95a1dc3 100644
--- a/app/cmd/migrate.go
+++ b/app/cmd/migrate.go
@@ -17,35 +17,83 @@ var migrateCmd = &cobra.Command{
Long: `Up and down migrations`,
}
-var migrateUp = &cobra.Command{
- Use: "up",
- Short: "Migrate up",
- Long: `Up migrations`,
- RunE: func(cmd *cobra.Command, args []string) error {
- db, err := sql.Open("sqlite3", dbFile)
- if err != nil {
- return fmt.Errorf("open db failed: %w", err)
- }
- defer db.Close()
-
- driver, err := sqlite.WithInstance(db, &sqlite.Config{})
- if err != nil {
- return fmt.Errorf("failed create migration driver: %w", err)
- }
- sourceDriver, err := iofs.New(migrations.FS, ".")
- if err != nil {
- return fmt.Errorf("failed open migrations: %w", err)
- }
-
- m, err := migrate.NewWithInstance("fs", sourceDriver, "sqlite3", driver)
- if err != nil {
- return fmt.Errorf("open migration failed: %w", err)
- }
-
- if err := m.Up(); err != nil && err != migrate.ErrNoChange {
- return fmt.Errorf("do migration failed: %w", err)
- }
-
- return nil
- },
+func init() {
+ migrateCmd.AddCommand(
+ &cobra.Command{
+ Use: "up",
+ Short: "Migrate up",
+ Long: `Up migrations`,
+ RunE: up,
+ },
+ &cobra.Command{
+ Use: "down",
+ Short: "Migrate down",
+ Long: `Down migrations`,
+ RunE: down,
+ },
+ &cobra.Command{
+ Use: "drop",
+ Short: "Drop db",
+ Long: `Deletes everything in the database`,
+ RunE: drop,
+ },
+ )
+}
+
+func up(_ *cobra.Command, _ []string) error {
+ m, err := initMigrate()
+ if err != nil {
+ return fmt.Errorf("open migration failed: %w", err)
+ }
+ defer m.Close()
+ if err := m.Up(); err != nil && err != migrate.ErrNoChange {
+ return fmt.Errorf("do migration failed: %w", err)
+ }
+
+ return nil
+}
+
+func down(_ *cobra.Command, _ []string) error {
+ m, err := initMigrate()
+ if err != nil {
+ return fmt.Errorf("open migration failed: %w", err)
+ }
+ defer m.Close()
+ if err := m.Down(); err != nil && err != migrate.ErrNoChange {
+ return fmt.Errorf("do migration failed: %w", err)
+ }
+
+ return nil
+}
+
+func drop(_ *cobra.Command, _ []string) error {
+ m, err := initMigrate()
+ if err != nil {
+ return fmt.Errorf("open migration failed: %w", err)
+ }
+ defer m.Close()
+ if err := m.Drop(); err != nil && err != migrate.ErrNoChange {
+ return fmt.Errorf("do migration failed: %w", err)
+ }
+
+ return nil
+}
+
+func initMigrate() (*migrate.Migrate, error) {
+ db, err := sql.Open("sqlite3", dbFile)
+ if err != nil {
+ return nil, fmt.Errorf("open db failed: %w", err)
+ }
+ defer db.Close()
+
+ driver, err := sqlite.WithInstance(db, &sqlite.Config{})
+ if err != nil {
+ return nil, fmt.Errorf("failed create migration driver: %w", err)
+ }
+ sourceDriver, err := iofs.New(migrations.FS, ".")
+ if err != nil {
+ return nil, fmt.Errorf("failed open migrations: %w", err)
+ }
+
+ return migrate.NewWithInstance("fs", sourceDriver, "sqlite3", driver)
}
diff --git a/app/cmd/root.go b/app/cmd/root.go
index 33c3642..5803166 100644
--- a/app/cmd/root.go
+++ b/app/cmd/root.go
@@ -19,10 +19,14 @@ var (
func init() {
cobra.OnInitialize(initLogger)
cobra.OnInitialize(initConfig)
- rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "gorum.yaml", "config file (default is 'gorum.yaml')")
- rootCmd.PersistentFlags().StringVar(&dbFile, "db", "gorum.db", "database file (default is 'gorum.db')")
+ rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "gorum.yaml", "config file")
+ rootCmd.PersistentFlags().StringVar(&dbFile, "db", "gorum.db", "database file")
rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "verbose debug output")
viper.BindPFlag("db", serverCmd.Flags().Lookup("db"))
+
+ rootCmd.AddCommand(serverCmd)
+ rootCmd.AddCommand(migrateCmd)
+ rootCmd.AddCommand(userCmd)
}
func initLogger() {
@@ -43,8 +47,6 @@ func initConfig() {
}
func Execute() {
- rootCmd.AddCommand(serverCmd)
-
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
diff --git a/app/cmd/serve.go b/app/cmd/serve.go
index 5593c32..e2d2843 100644
--- a/app/cmd/serve.go
+++ b/app/cmd/serve.go
@@ -2,7 +2,6 @@ package cmd
import (
"context"
- "database/sql"
"fmt"
"log/slog"
"net"
@@ -15,10 +14,8 @@ import (
"github.com/michaeljs1990/sqlitestore"
"github.com/spf13/cobra"
"github.com/spf13/viper"
- "github.com/uptrace/bun"
- "github.com/uptrace/bun/dialect/sqlitedialect"
- "github.com/uptrace/bun/extra/bundebug"
"gitrepo.ru/neonxp/gorum/contextlib"
+ "gitrepo.ru/neonxp/gorum/db"
"gitrepo.ru/neonxp/gorum/middleware"
"gitrepo.ru/neonxp/gorum/repository"
"gitrepo.ru/neonxp/gorum/routes"
@@ -42,9 +39,9 @@ var (
)
func init() {
- serverCmd.PersistentFlags().StringVar(&theme, "theme", "default", "theme to use (default is 'default')")
- serverCmd.PersistentFlags().StringVar(&listen, "listen", ":8000", "bind address to listen (default is ':8000')")
- serverCmd.PersistentFlags().StringVar(&sessionSecret, "session_secret", "s3cr3t", "sessions secret (default is 's3cr3t')")
+ serverCmd.PersistentFlags().StringVar(&theme, "theme", "default", "theme to use")
+ serverCmd.PersistentFlags().StringVar(&listen, "listen", ":8000", "bind address to listen")
+ serverCmd.PersistentFlags().StringVar(&sessionSecret, "session_secret", "s3cr3t", "sessions secret")
viper.BindPFlag("theme", serverCmd.Flags().Lookup("theme"))
viper.BindPFlag("listen", serverCmd.Flags().Lookup("listen"))
viper.BindPFlag("session_secret", serverCmd.Flags().Lookup("session_secret"))
@@ -60,14 +57,12 @@ func serve(ctx context.Context) error {
)
ctx = context.WithValue(ctx, contextlib.ThemeKey, theme)
- db, err := sql.Open("sqlite3", dbFile)
+ orm, err := db.GetDB(dbFile)
if err != nil {
- return fmt.Errorf("open db failed: %w", err)
+ return err
}
- defer db.Close()
- orm := bun.NewDB(db, sqlitedialect.New())
- orm.AddQueryHook(bundebug.NewQueryHook(bundebug.WithVerbose(true)))
+ defer orm.Close()
userRepo := repository.NewUser(orm)
nodeRepo := repository.NewNode(orm)
@@ -82,11 +77,7 @@ func serve(ctx context.Context) error {
_ = utils.Render(c, views.ErrorPage(err))
}
- e.Server.BaseContext = func(l net.Listener) context.Context {
- return ctx
- }
-
- sessionStore, err := sqlitestore.NewSqliteStoreFromConnection(db, "sessions", "", 0, []byte(sessionSecret))
+ sessionStore, err := sqlitestore.NewSqliteStoreFromConnection(orm.DB, "sessions", "", 0, []byte(sessionSecret))
if err != nil {
return fmt.Errorf("failed init session store: %w", err)
}
@@ -94,14 +85,14 @@ func serve(ctx context.Context) error {
e.Use(
echomiddleware.Recover(),
echomiddleware.Gzip(),
- echomiddleware.CSRFWithConfig(echomiddleware.CSRFConfig{
- Skipper: echomiddleware.DefaultSkipper,
- TokenLength: 32,
- TokenLookup: "form:" + echo.HeaderXCSRFToken,
- ContextKey: "csrf",
- CookieName: "_csrf",
- CookieMaxAge: 86400,
- }),
+ // echomiddleware.CSRFWithConfig(echomiddleware.CSRFConfig{
+ // Skipper: echomiddleware.DefaultSkipper,
+ // TokenLength: 32,
+ // TokenLookup: "form:" + echo.HeaderXCSRFToken,
+ // ContextKey: "csrf",
+ // CookieName: "_csrf",
+ // CookieMaxAge: 86400,
+ // }),
session.Middleware(sessionStore),
middleware.UserMiddleware(),
)
@@ -113,9 +104,12 @@ func serve(ctx context.Context) error {
e.POST("/logout", r.Logout)
e.GET("/", r.Node)
- e.GET("/n/:id", r.Node)
- e.GET("/n/:id/new", r.NewPost)
- e.POST("/n/:id/new", r.NewPost)
+ e.GET("/p/:id", r.Node)
+ e.GET("/p/:id/new", r.NewPost)
+ e.POST("/p/:id/new", r.NewPost)
+ e.GET("/t/:id", r.Node)
+ e.GET("/t/:id/new", r.NewTopic)
+ e.POST("/t/:id/new", r.NewTopic)
e.StaticFS("/assets", assets.FS)
@@ -125,6 +119,9 @@ func serve(ctx context.Context) error {
Addr: listen,
Handler: e,
ErrorLog: slog.NewLogLogger(slog.Default().Handler(), slog.LevelError),
+ ConnContext: func(cctx context.Context, c net.Conn) context.Context {
+ return ctx
+ },
}
if err := server.ListenAndServe(); err != http.ErrServerClosed {
return fmt.Errorf("server failed: %w", err)
diff --git a/app/cmd/user.go b/app/cmd/user.go
new file mode 100644
index 0000000..673c7b8
--- /dev/null
+++ b/app/cmd/user.go
@@ -0,0 +1,80 @@
+package cmd
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+
+ "github.com/spf13/cobra"
+ "gitrepo.ru/neonxp/gorum/db"
+ "gitrepo.ru/neonxp/gorum/models"
+ "gitrepo.ru/neonxp/gorum/repository"
+)
+
+var userCmd = &cobra.Command{
+ Use: "user",
+ Short: "User managment",
+}
+
+var createUserCmd = &cobra.Command{
+ Use: "add",
+ Args: cobra.ExactArgs(3),
+ ArgAliases: []string{"username", "email", "role"},
+ RunE: func(cmd *cobra.Command, args []string) error {
+ orm, err := db.GetDB(dbFile)
+ if err != nil {
+ return fmt.Errorf("failed init db: %w", err)
+ }
+ username := args[0]
+ email := args[1]
+ role := args[2]
+ iRole := models.RoleUser
+ switch role {
+ case "admin":
+ iRole = models.RoleAdmin
+ case "moderator":
+ iRole = models.RoleModerator
+ }
+ reader := bufio.NewReader(os.Stdin)
+ fmt.Printf("Enter password for user %s: ", username)
+ password, _ := reader.ReadString('\n')
+
+ ur := repository.NewUser(orm)
+ id, err := ur.Create(cmd.Context(), email, password, username, iRole)
+ if err != nil {
+ return fmt.Errorf("failed create user: %w", err)
+ }
+
+ fmt.Printf("Created user %s (id=%d, email=%s, role_id=%d)\n", username, id, email, iRole)
+
+ return nil
+ },
+}
+
+var listUserCmd = &cobra.Command{
+ Use: "list",
+ RunE: func(cmd *cobra.Command, args []string) error {
+ orm, err := db.GetDB(dbFile)
+ if err != nil {
+ return fmt.Errorf("failed init db: %w", err)
+ }
+
+ ur := repository.NewUser(orm)
+ users, err := ur.List(cmd.Context())
+ if err != nil {
+ return err
+ }
+
+ fmt.Printf("ID\tUsername\tEmail\tRole\n")
+ for _, u := range users {
+ fmt.Printf("%d\t%s\t%s\t%d\n", u.ID, u.Username, u.Email, u.Role)
+ }
+
+ return nil
+ },
+}
+
+func init() {
+ userCmd.AddCommand(createUserCmd)
+ userCmd.AddCommand(listUserCmd)
+}