From b54275771e616679fae5827abe8066f1f6ae2d3a Mon Sep 17 00:00:00 2001 From: hexxa Date: Sat, 24 Sep 2022 21:14:08 +0800 Subject: [PATCH] fix(server): add initer --- src/server/init_deps.go | 129 +++++++++++++++++++++--------------- src/server/init_handlers.go | 15 ++--- src/server/server.go | 5 +- 3 files changed, 85 insertions(+), 64 deletions(-) diff --git a/src/server/init_deps.go b/src/server/init_deps.go index 61fada5..554e24e 100644 --- a/src/server/init_deps.go +++ b/src/server/init_deps.go @@ -6,6 +6,7 @@ import ( "crypto/sha1" "errors" "fmt" + "io" "os" "path" @@ -31,23 +32,37 @@ import ( "github.com/ihexxa/quickshare/src/worker/localworker" ) -func initDeps(cfg gocfg.ICfg) *depidx.Deps { - ider := simpleidgen.New() - logger := initLogger(cfg) - jwtEncDec := initJWT(cfg, logger) - workers := initWorkerPool(cfg, logger) - filesystem, err := initFs(cfg, ider, logger) - if err != nil { - logger.Fatalf("failed to init DB: %s", err) - } - quickshareDb, err := initDb(cfg, filesystem) - if err != nil { - logger.Fatalf("failed to init DB: %s", err) - } - rateLimiter := initRateLimiter(cfg, quickshareDb) - fileIndex := initSearchIndex(cfg, filesystem, logger) +type Initer struct { + cfg gocfg.ICfg + input io.Reader + output io.Writer +} - deps := depidx.NewDeps(cfg) +func NewIniter(cfg gocfg.ICfg) *Initer { + return &Initer{ + cfg: cfg, + input: os.Stdin, + output: os.Stdout, + } +} + +func (it *Initer) InitDeps() *depidx.Deps { + ider := simpleidgen.New() + logger := it.initLogger() + jwtEncDec := it.initJWT(logger) + workers := it.initWorkerPool(logger) + filesystem, err := it.initFs(ider, logger) + if err != nil { + logger.Fatalf("failed to init DB: %s", err) + } + quickshareDb, err := it.initDb(filesystem) + if err != nil { + logger.Fatalf("failed to init DB: %s", err) + } + rateLimiter := it.initRateLimiter(quickshareDb) + fileIndex := it.initSearchIndex(filesystem, logger) + + deps := depidx.NewDeps(it.cfg) deps.SetDB(quickshareDb) deps.SetFS(filesystem) deps.SetToken(jwtEncDec) @@ -60,12 +75,12 @@ func initDeps(cfg gocfg.ICfg) *depidx.Deps { return deps } -func initLogger(cfg gocfg.ICfg) *zap.SugaredLogger { +func (it *Initer) initLogger() *zap.SugaredLogger { fileWriter := zapcore.AddSync(&lumberjack.Logger{ - Filename: path.Join(cfg.GrabString("Fs.Root"), "quickshare.log"), - MaxSize: cfg.IntOr("Log.MaxSize", 50), // megabytes - MaxBackups: cfg.IntOr("Log.MaxBackups", 2), - MaxAge: cfg.IntOr("Log.MaxAge", 31), // days + Filename: path.Join(it.cfg.GrabString("Fs.Root"), "quickshare.log"), + MaxSize: it.cfg.IntOr("Log.MaxSize", 50), // megabytes + MaxBackups: it.cfg.IntOr("Log.MaxBackups", 2), + MaxAge: it.cfg.IntOr("Log.MaxAge", 31), // days }) stdoutWriter := zapcore.AddSync(os.Stdout) @@ -79,13 +94,13 @@ func initLogger(cfg gocfg.ICfg) *zap.SugaredLogger { return zap.New(core).Sugar() } -func initJWT(cfg gocfg.ICfg, logger *zap.SugaredLogger) cryptoutil.ITokenEncDec { - secret, ok := cfg.String("ENV.TOKENSECRET") +func (it *Initer) initJWT(logger *zap.SugaredLogger) cryptoutil.ITokenEncDec { + secret, ok := it.cfg.String("ENV.TOKENSECRET") if !ok { b := make([]byte, 32) _, err := rand.Read(b) if err != nil { - panic(fmt.Sprintf("make rand token error: %s", err)) + logger.Fatalf("make rand token error: %s", err) } secret = string(b) logger.Info("warning: TOKENSECRET is not set, a random token is generated") @@ -94,24 +109,24 @@ func initJWT(cfg gocfg.ICfg, logger *zap.SugaredLogger) cryptoutil.ITokenEncDec return jwt.NewJWTEncDec(secret) } -func initRateLimiter(cfg gocfg.ICfg, quickshareDb db.IDBQuickshare) iolimiter.ILimiter { - limiterCap := cfg.IntOr("Users.LimiterCapacity", 10000) - limiterCyc := cfg.IntOr("Users.LimiterCyc", 1000) +func (it *Initer) initRateLimiter(quickshareDb db.IDBQuickshare) iolimiter.ILimiter { + limiterCap := it.cfg.IntOr("Users.LimiterCapacity", 10000) + limiterCyc := it.cfg.IntOr("Users.LimiterCyc", 1000) return iolimiter.NewIOLimiter(limiterCap, limiterCyc, quickshareDb) } -func initWorkerPool(cfg gocfg.ICfg, logger *zap.SugaredLogger) worker.IWorkerPool { - queueSize := cfg.GrabInt("Workers.QueueSize") - sleepCyc := cfg.GrabInt("Workers.SleepCyc") - workerCount := cfg.GrabInt("Workers.WorkerCount") +func (it *Initer) initWorkerPool(logger *zap.SugaredLogger) worker.IWorkerPool { + queueSize := it.cfg.GrabInt("Workers.QueueSize") + sleepCyc := it.cfg.GrabInt("Workers.SleepCyc") + workerCount := it.cfg.GrabInt("Workers.WorkerCount") workers := localworker.NewWorkerPool(queueSize, sleepCyc, workerCount, logger) workers.Start() return workers } -func initSearchIndex(cfg gocfg.ICfg, filesystem fs.ISimpleFS, logger *zap.SugaredLogger) fileindex.IFileIndex { - searchResultLimit := cfg.GrabInt("Server.SearchResultLimit") +func (it *Initer) initSearchIndex(filesystem fs.ISimpleFS, logger *zap.SugaredLogger) fileindex.IFileIndex { + searchResultLimit := it.cfg.GrabInt("Server.SearchResultLimit") fileIndex := fileindex.NewFileTreeIndex(filesystem, "/", searchResultLimit) indexInited := false @@ -137,11 +152,11 @@ func initSearchIndex(cfg gocfg.ICfg, filesystem fs.ISimpleFS, logger *zap.Sugare return fileIndex } -func initFs(cfg gocfg.ICfg, idGenerator idgen.IIDGen, logger *zap.SugaredLogger) (fs.ISimpleFS, error) { - rootPath := cfg.GrabString("Fs.Root") - opensLimit := cfg.GrabInt("Fs.OpensLimit") - openTTL := cfg.GrabInt("Fs.OpenTTL") - readerTTL := cfg.GrabInt("Server.WriteTimeout") / 1000 // millisecond -> second +func (it *Initer) initFs(idGenerator idgen.IIDGen, logger *zap.SugaredLogger) (fs.ISimpleFS, error) { + rootPath := it.cfg.GrabString("Fs.Root") + opensLimit := it.cfg.GrabInt("Fs.OpensLimit") + openTTL := it.cfg.GrabInt("Fs.OpenTTL") + readerTTL := it.cfg.GrabInt("Server.WriteTimeout") / 1000 // millisecond -> second info, err := os.Stat(rootPath) if err != nil { @@ -160,8 +175,8 @@ func initFs(cfg gocfg.ICfg, idGenerator idgen.IIDGen, logger *zap.SugaredLogger) return local.NewLocalFS(rootPath, 0660, opensLimit, openTTL, readerTTL, idGenerator), nil } -func initDb(cfg gocfg.ICfg, filesystem fs.ISimpleFS) (db.IDBQuickshare, error) { - dbPath := cfg.GrabString("Db.DbPath") +func (it *Initer) initDb(filesystem fs.ISimpleFS) (db.IDBQuickshare, error) { + dbPath := it.cfg.GrabString("Db.DbPath") dbDir := path.Dir(dbPath) sqliteDB, err := sqlite.NewSQLite(path.Join(filesystem.Root(), dbPath)) @@ -192,19 +207,23 @@ func initDb(cfg gocfg.ICfg, filesystem fs.ISimpleFS) (db.IDBQuickshare, error) { return nil, fmt.Errorf("failed to create path for db: %w", err) } - adminName, ok = cfg.String("ENV.DEFAULTADMIN") + adminName, ok = it.cfg.String("ENV.DEFAULTADMIN") if !ok || adminName == "" { - fmt.Println("Please input admin name: ") - fmt.Scanf("%s", &adminName) + fmt.Fprintln(it.output, "Please input admin name: ") + fmt.Fscanf(it.input, "%s", &adminName) } - adminPwd, _ := cfg.String("ENV.DEFAULTADMINPWD") + adminPwd, _ := it.cfg.String("ENV.DEFAULTADMINPWD") if adminPwd == "" { adminPwd, err = generatePwd() if err != nil { return nil, fmt.Errorf("generate password error: %w", err) } - fmt.Printf("password is generated: %s, please update it immediately after login\n", adminPwd) + fmt.Fprintf( + it.output, + "password is generated: %s, please update it immediately after login\n", + adminPwd, + ) } pwdHash, err = bcrypt.GenerateFromPassword([]byte(adminPwd), 10) @@ -212,22 +231,24 @@ func initDb(cfg gocfg.ICfg, filesystem fs.ISimpleFS) (db.IDBQuickshare, error) { return nil, fmt.Errorf("hashing password error: %w", err) } - cfg.SetString("ENV.DEFAULTADMIN", adminName) - cfg.SetString("ENV.DEFAULTADMINPWD", string(pwdHash)) + it.cfg.SetString("ENV.DEFAULTADMIN", adminName) + it.cfg.SetString("ENV.DEFAULTADMINPWD", adminPwd) + it.cfg.SetString("ENV.DEFAULTADMINPWDHASH", string(pwdHash)) siteCfg := &db.SiteConfig{ ClientCfg: &db.ClientConfig{ - SiteName: cfg.StringOr("Site.ClientCfg.SiteName", "Quickshare"), - SiteDesc: cfg.StringOr("Site.ClientCfg.SiteDesc", "Quick and simple file sharing"), + SiteName: it.cfg.StringOr("Site.ClientCfg.SiteName", "Quickshare"), + SiteDesc: it.cfg.StringOr("Site.ClientCfg.SiteDesc", "Quick and simple file sharing"), Bg: &db.BgConfig{ - Url: cfg.StringOr("Site.ClientCfg.Bg.Url", ""), - Repeat: cfg.StringOr("Site.ClientCfg.Bg.Repeat", "repeat"), - Position: cfg.StringOr("Site.ClientCfg.Bg.Position", "center"), - Align: cfg.StringOr("Site.ClientCfg.Bg.Align", "fixed"), - BgColor: cfg.StringOr("Site.ClientCfg.Bg.BgColor", ""), + Url: it.cfg.StringOr("Site.ClientCfg.Bg.Url", ""), + Repeat: it.cfg.StringOr("Site.ClientCfg.Bg.Repeat", "repeat"), + Position: it.cfg.StringOr("Site.ClientCfg.Bg.Position", "center"), + Align: it.cfg.StringOr("Site.ClientCfg.Bg.Align", "fixed"), + BgColor: it.cfg.StringOr("Site.ClientCfg.Bg.BgColor", ""), }, }, } + err = dbQuickshare.Init(context.TODO(), adminName, string(pwdHash), siteCfg) if err != nil { return nil, fmt.Errorf("failed to init tables: %w %s", err, dbPath) diff --git a/src/server/init_handlers.go b/src/server/init_handlers.go index 95f5003..26e56ca 100644 --- a/src/server/init_handlers.go +++ b/src/server/init_handlers.go @@ -7,7 +7,6 @@ import ( "github.com/gin-contrib/static" "github.com/gin-gonic/gin" - "github.com/ihexxa/gocfg" "github.com/ihexxa/quickshare/src/depidx" "github.com/ihexxa/quickshare/src/handlers/fileshdr" @@ -16,26 +15,26 @@ import ( qsstatic "github.com/ihexxa/quickshare/static" ) -func initHandlers(cfg gocfg.ICfg, deps *depidx.Deps) (*gin.Engine, error) { +func (it *Initer) InitHandlers(deps *depidx.Deps) (*gin.Engine, error) { router := gin.Default() // handlers - userHdrs, err := multiusers.NewMultiUsersSvc(cfg, deps) + userHdrs, err := multiusers.NewMultiUsersSvc(it.cfg, deps) if err != nil { return nil, fmt.Errorf("new users svc error: %w", err) } - adminName := cfg.GrabString("ENV.DEFAULTADMIN") + adminName := it.cfg.GrabString("ENV.DEFAULTADMIN") _, err = userHdrs.Init(context.TODO(), adminName) if err != nil { return nil, fmt.Errorf("failed to init user handlers: %w", err) } - fileHdrs, err := fileshdr.NewFileHandlers(cfg, deps) + fileHdrs, err := fileshdr.NewFileHandlers(it.cfg, deps) if err != nil { return nil, fmt.Errorf("new files service error: %w", err) } - settingsSvc, err := settings.NewSettingsSvc(cfg, deps) + settingsSvc, err := settings.NewSettingsSvc(it.cfg, deps) if err != nil { return nil, fmt.Errorf("new setting service error: %w", err) } @@ -44,11 +43,11 @@ func initHandlers(cfg gocfg.ICfg, deps *depidx.Deps) (*gin.Engine, error) { router.Use(userHdrs.AuthN()) router.Use(userHdrs.APIAccessControl()) - publicPath, ok := cfg.String("Server.PublicPath") + publicPath, ok := it.cfg.String("Server.PublicPath") if !ok || publicPath == "" { return nil, errors.New("publicPath not found or empty") } - if cfg.BoolOr("Server.Debug", false) { + if it.cfg.BoolOr("Server.Debug", false) { router.Use(static.Serve("/", static.LocalFile(publicPath, false))) } else { embedFs, err := qsstatic.NewEmbedStaticFS() diff --git a/src/server/server.go b/src/server/server.go index cb492ba..22f419d 100644 --- a/src/server/server.go +++ b/src/server/server.go @@ -31,8 +31,9 @@ func NewServer(cfg gocfg.ICfg) (*Server, error) { gin.SetMode(gin.ReleaseMode) } - deps := initDeps(cfg) - router, err := initHandlers(cfg, deps) + initer := NewIniter(cfg) + deps := initer.InitDeps() + router, err := initer.InitHandlers(deps) if err != nil { return nil, fmt.Errorf("init handlers error: %w", err) }