diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/cmd/migrate.go | 110 | ||||
-rw-r--r-- | app/cmd/root.go | 10 | ||||
-rw-r--r-- | app/cmd/serve.go | 53 | ||||
-rw-r--r-- | app/cmd/user.go | 80 |
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) +} |